OSDN Git Service

Merge branch 'x86/iommu' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux...
authorJesse Barnes <jbarnes@hobbes.lan>
Mon, 28 Jul 2008 21:31:10 +0000 (14:31 -0700)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Mon, 28 Jul 2008 21:31:10 +0000 (14:31 -0700)
2004 files changed:
Documentation/DMA-API.txt
Documentation/Intel-IOMMU.txt
Documentation/SubmittingPatches
Documentation/accounting/taskstats-struct.txt
Documentation/arm/Interrupts
Documentation/cpu-freq/governors.txt
Documentation/edac.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/omfs.txt [new file with mode: 0644]
Documentation/filesystems/proc.txt
Documentation/filesystems/relay.txt
Documentation/filesystems/vfs.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/keys.txt
Documentation/leds-class.txt
Documentation/local_ops.txt
Documentation/networking/bonding.txt
Documentation/networking/can.txt
Documentation/networking/packet_mmap.txt
Documentation/networking/tc-actions-env-rules.txt
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/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/kernel/osf_sys.c
arch/alpha/mm/init.c
arch/alpha/mm/numa.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/common/dmabounce.c
arch/arm/common/locomo.c
arch/arm/common/sa1111.c
arch/arm/configs/eseries_pxa_defconfig
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-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-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/fault-armv.c
arch/arm/plat-mxc/gpio.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/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/time.c
arch/avr32/mach-at32ap/at32ap700x.c
arch/avr32/mach-at32ap/hsmc.c
arch/avr32/mm/init.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/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/kernel/kgdb.c
arch/cris/arch-v32/kernel/kgdb.c
arch/cris/mm/init.c
arch/frv/kernel/gdb-stub.c
arch/frv/mm/init.c
arch/h8300/mm/init.c
arch/ia64/hp/common/hwsw_iommu.c
arch/ia64/hp/common/sba_iommu.c
arch/ia64/kernel/perfmon.c
arch/ia64/kvm/kvm-ia64.c
arch/ia64/sn/pci/pci_dma.c
arch/m32r/mm/init.c
arch/m68k/mm/init.c
arch/m68knommu/mm/init.c
arch/mips/mm/Makefile
arch/mips/mm/dma-default.c
arch/mips/mm/pgtable.c [deleted file]
arch/mn10300/kernel/gdb-stub.c
arch/mn10300/mm/pgtable.c
arch/parisc/hpux/sys_hpux.c
arch/powerpc/Kconfig
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/legacy_serial.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/sysfs.c
arch/powerpc/kernel/vio.c
arch/powerpc/kvm/44x_tlb.c
arch/powerpc/kvm/emulate.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/platforms/cell/celleb_scc_pciex.c
arch/powerpc/platforms/cell/spider-pci.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/iseries/mf.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/powermac/udbg_scc.c
arch/powerpc/platforms/pseries/cmm.c
arch/s390/kernel/kprobes.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/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/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/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/init.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 100% 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 100% 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 100% similarity]
arch/sparc/include/asm/page_64.h [moved from include/asm-sparc/page_64.h with 100% 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 95% similarity]
arch/sparc/include/asm/thread_info_64.h [moved from include/asm-sparc/thread_info_64.h with 97% 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 100% similarity]
arch/sparc/include/asm/unistd_64.h [moved from include/asm-sparc/unistd_64.h with 100% 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/sparc64/Kconfig
arch/sparc64/kernel/compat_audit.c
arch/sparc64/kernel/entry.h
arch/sparc64/kernel/ptrace.c
arch/sparc64/kernel/rtrap.S
arch/sparc64/kernel/signal.c
arch/sparc64/kernel/signal32.c
arch/sparc64/kernel/syscalls.S
arch/sparc64/mm/init.c
arch/um/kernel/mem.c
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/ia32/ia32_aout.c
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/head_32.S
arch/x86/kernel/machine_kexec_32.c
arch/x86/kernel/machine_kexec_64.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/relocate_kernel_32.S
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/Makefile
arch/x86/mm/gup.c [new file with mode: 0644]
arch/x86/mm/init_64.c
arch/x86/mm/pgtable_32.c
arch/xtensa/mm/init.c
block/as-iosched.c
block/blk-map.c
drivers/acpi/processor_idle.c
drivers/ata/pata_ixp4xx_cf.c
drivers/base/core.c
drivers/base/isa.c
drivers/base/memory.c
drivers/base/sys.c
drivers/char/dsp56k.c
drivers/char/hw_random/intel-rng.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/rtc.c
drivers/char/ser_a2232.c
drivers/char/tpm/tpm.c
drivers/char/tpm/tpm_bios.c
drivers/char/tpm/tpm_tis.c
drivers/char/vme_scc.c
drivers/cpuidle/cpuidle.c
drivers/crypto/talitos.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/memmap.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/infiniband/core/ucm.c
drivers/infiniband/core/ucma.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_eq.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/input/keyboard/sh_keysc.c
drivers/input/misc/uinput.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/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/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/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-fx2-cmd.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-i2c-core.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_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-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/mfd/asic3.c
drivers/mfd/tc6393xb.c
drivers/misc/Kconfig
drivers/misc/atmel-ssc.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/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/ibmveth.c
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/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/spider_net.c
drivers/net/tc35815.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_cs.c
drivers/parport/parport_pc.c
drivers/parport/procfs.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/pci.c
drivers/pci/probe.c
drivers/pcmcia/soc_common.c
drivers/pnp/base.h
drivers/pnp/card.c
drivers/pnp/quirks.c
drivers/s390/kvm/Makefile
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/ibmvstgt.c
drivers/scsi/ibmvscsi/rpa_vscsi.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/sym53c8xx_2/sym_hipd.c
drivers/scsi/tmscsim.c
drivers/scsi/wd7000.c
drivers/scsi/zalon.c
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
drivers/spi/atmel_spi.c
drivers/spi/au1550_spi.c
drivers/spi/omap2_mcspi.c
drivers/spi/pxa2xx_spi.c
drivers/spi/spi.c
drivers/spi/spi_imx.c
drivers/usb/mon/mon_text.c
drivers/usb/serial/ipaq.c
drivers/video/am200epd.c
drivers/video/console/sticon.c
drivers/video/console/sticore.c
drivers/video/fbmem.c
drivers/video/macfb.c
drivers/video/omap/sossi.c
drivers/video/pxafb.c
drivers/video/sticore.h
drivers/video/stifb.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/attr.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_som.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/dir.c
fs/coda/inode.c
fs/coda/pioctl.c
fs/compat.c
fs/dcache.c
fs/direct-io.c
fs/dlm/lock.c
fs/dlm/lowcomms.c
fs/dlm/user.c
fs/ecryptfs/inode.c
fs/ecryptfs/main.c
fs/efs/super.c
fs/exec.c
fs/ext2/acl.c
fs/ext2/acl.h
fs/ext2/super.c
fs/ext3/acl.c
fs/ext3/acl.h
fs/ext3/super.c
fs/ext4/acl.c
fs/ext4/acl.h
fs/ext4/super.c
fs/fat/cache.c
fs/fat/file.c
fs/fat/inode.c
fs/fcntl.c
fs/fifo.c
fs/file.c
fs/file_table.c
fs/fuse/dir.c
fs/fuse/file.c
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/inode.c
fs/hfs/super.c
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/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/locks.c
fs/minix/inode.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/super.c
fs/nfs/unlink.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/pipe.c
fs/proc/array.c
fs/proc/base.c
fs/proc/generic.c
fs/proc/inode.c
fs/proc/proc_sysctl.c
fs/qnx4/inode.c
fs/reiserfs/super.c
fs/reiserfs/xattr.c
fs/romfs/inode.c
fs/smbfs/file.c
fs/smbfs/inode.c
fs/splice.c
fs/stat.c
fs/sysfs/dir.c
fs/sysfs/file.c
fs/sysfs/group.c
fs/sysv/inode.c
fs/ubifs/file.c
fs/ubifs/super.c
fs/udf/super.c
fs/ufs/super.c
fs/utimes.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/asm-alpha/dma-mapping.h
include/asm-alpha/namei.h [deleted file]
include/asm-alpha/pci.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-sa1100/ide.h
include/asm-arm/bitops.h
include/asm-arm/cacheflush.h
include/asm-arm/dma-mapping.h
include/asm-arm/irq.h
include/asm-arm/namei.h [deleted file]
include/asm-arm/pci.h
include/asm-arm/plat-s3c/iic.h
include/asm-avr32/arch-at32ap/board.h
include/asm-avr32/dma-mapping.h
include/asm-avr32/namei.h [deleted file]
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/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/processor.h
include/asm-cris/dma-mapping.h
include/asm-cris/namei.h [deleted file]
include/asm-frv/dma-mapping.h
include/asm-frv/namei.h [deleted file]
include/asm-generic/dma-mapping-broken.h
include/asm-generic/dma-mapping.h
include/asm-generic/gpio.h
include/asm-generic/pci-dma-compat.h
include/asm-generic/syscall.h [new file with mode: 0644]
include/asm-generic/vmlinux.lds.h
include/asm-h8300/namei.h [deleted file]
include/asm-ia64/machvec.h
include/asm-ia64/namei.h [deleted file]
include/asm-m32r/namei.h [deleted file]
include/asm-m68k/dma-mapping.h
include/asm-m68k/namei.h [deleted file]
include/asm-m68knommu/namei.h [deleted file]
include/asm-mips/dma-mapping.h
include/asm-mips/namei.h [deleted file]
include/asm-mn10300/dma-mapping.h
include/asm-mn10300/namei.h [deleted file]
include/asm-parisc/cacheflush.h
include/asm-parisc/dma-mapping.h
include/asm-parisc/namei.h [deleted file]
include/asm-powerpc/dma-mapping.h
include/asm-powerpc/kvm_ppc.h
include/asm-powerpc/namei.h [deleted file]
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/ptrace.h
include/asm-powerpc/signal.h
include/asm-powerpc/smp.h
include/asm-powerpc/syscall.h [new file with mode: 0644]
include/asm-powerpc/thread_info.h
include/asm-powerpc/topology.h
include/asm-s390/kvm_host.h
include/asm-s390/namei.h [deleted file]
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/hw_irq.h
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/sh7763rdp.h [new file with mode: 0644]
include/asm-sh/sh7785lcr.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/namei.h [deleted file]
include/asm-sparc/namei_32.h [deleted file]
include/asm-sparc/namei_64.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/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/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/namei.h [deleted file]
include/asm-v850/namei.h [deleted file]
include/asm-x86/device.h
include/asm-x86/dma-mapping.h
include/asm-x86/gpio.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/pgtable.h
include/asm-x86/swiotlb.h
include/asm-x86/uaccess.h
include/asm-xtensa/dma-mapping.h
include/asm-xtensa/namei.h [deleted file]
include/linux/aio.h
include/linux/coda_linux.h
include/linux/crash_dump.h
include/linux/fs.h
include/linux/fs_struct.h
include/linux/hugetlb.h
include/linux/i2o.h
include/linux/init.h
include/linux/jffs2.h
include/linux/kexec.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/maple.h
include/linux/memstick.h
include/linux/mlx4/qp.h
include/linux/mm.h
include/linux/mmc/card.h
include/linux/mmc/host.h
include/linux/mount.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/xip.h
include/linux/namei.h
include/linux/nfs_fs.h
include/linux/of.h
include/linux/of_spi.h [new file with mode: 0644]
include/linux/pagemap.h
include/linux/parport.h
include/linux/pci_ids.h
include/linux/percpu.h
include/linux/proc_fs.h
include/linux/ptrace.h
include/linux/radix-tree.h
include/linux/reiserfs_xattr.h
include/linux/relay.h
include/linux/rtc.h
include/linux/rtnetlink.h
include/linux/sched.h
include/linux/security.h
include/linux/serio.h
include/linux/shmem_fs.h
include/linux/slab.h
include/linux/slub_def.h
include/linux/smp.h
include/linux/socket.h
include/linux/spi/spi.h
include/linux/ssb/ssb.h
include/linux/stop_machine.h
include/linux/suspend.h
include/linux/swap.h
include/linux/sysctl.h
include/linux/task_io_accounting.h
include/linux/task_io_accounting_ops.h
include/linux/tracehook.h [new file with mode: 0644]
include/linux/videodev.h
include/linux/videodev2.h
include/linux/videotext.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/net/af_unix.h
include/net/ip.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/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
init/Kconfig
init/do_mounts.c
init/do_mounts.h
init/main.c
ipc/mqueue.c
kernel/cgroup.c
kernel/cpu.c
kernel/exec_domain.c
kernel/exit.c
kernel/fork.c
kernel/irq/chip.c
kernel/irq/manage.c
kernel/kexec.c
kernel/kthread.c
kernel/module.c
kernel/power/main.c
kernel/power/power.h
kernel/ptrace.c
kernel/rcuclassic.c
kernel/relay.c
kernel/sched.c
kernel/signal.c
kernel/smp.c
kernel/softirq.c
kernel/softlockup.c
kernel/stop_machine.c
kernel/sys.c
kernel/sysctl.c
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace_irqsoff.c
kernel/trace/trace_sched_wakeup.c
kernel/tsacct.c
lib/Makefile
lib/debugobjects.c
lib/idr.c
lib/iomap.c
lib/kobject_uevent.c
lib/plist.c
lib/radix-tree.c
lib/show_mem.c [new file with mode: 0644]
lib/swiotlb.c
lib/syscall.c [new file with mode: 0644]
mm/Kconfig
mm/allocpercpu.c
mm/filemap.c
mm/filemap_xip.c
mm/hugetlb.c
mm/memory.c
mm/migrate.c
mm/nommu.c
mm/page-writeback.c
mm/page_alloc.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_state.c
mm/swapfile.c
mm/truncate.c
mm/util.c
mm/vmalloc.c
mm/vmscan.c
net/appletalk/ddp.c
net/bridge/netfilter/ebtable_filter.c
net/bridge/netfilter/ebtable_nat.c
net/core/datagram.c
net/core/dev.c
net/core/request_sock.c
net/core/skbuff.c
net/core/stream.c
net/core/user_dma.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/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/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/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/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/sched/sch_sfq.c
net/sctp/associola.c
net/socket.c
net/sunrpc/rpc_pipe.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sysctl_net.c
net/unix/af_unix.c
net/unix/garbage.c
net/xfrm/xfrm_algo.c
net/xfrm/xfrm_ipcomp.c
net/xfrm/xfrm_state.c
scripts/Makefile.headersinst
scripts/diffconfig [new file with mode: 0755]
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/setlocalversion
security/capability.c
security/security.c
security/selinux/hooks.c
security/smack/smack_lsm.c
sound/i2c/other/tea575x-tuner.c
sound/isa/cs423x/cs4236.c
sound/isa/opti9xx/opti92x-ad1848.c
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

index 80d1504..d8b63d1 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 c232190..21bc416 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 118ca6e..f79ad9f 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 b988d11..e7512c0 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
index 0d3dbf1..c202ed3 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.
 
index dcec056..5b0cfa6 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 ced5273..8eda3fb 100644 (file)
@@ -327,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.
 
index 721c71b..c239554 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
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 8c6384b..6455782 100644 (file)
@@ -931,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.
@@ -1474,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 094f2d2..510b722 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 b7522c6..c4d348d 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
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 bec9d81..914d07f 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 afe0d65..202e9db 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 bfdf7f3..e35efb0 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 5925c3c..59a69ec 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 d5c7a57..b56aacc 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 18860ad..6399557 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 4269a11..f4f8b1c 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 7fa7fe7..688dfe1 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 641d2af..297ba7b 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 db0cd51..07c53d5 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 01e716d..dcadf6f 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 99514ce..928a79c 100644 (file)
@@ -708,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.
 
@@ -1777,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
@@ -1799,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
@@ -1953,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 8962664..06da4d4 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 e938c44..bde473d 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 a810421..3920f28 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 4dbe413..5741ea8 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 d403e46..75143f0 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 9aef710..114b595 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 72aff61..6f6d117 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 2ad5e63..a4c53d8 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 8e1b025..34e87ec 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 c784a18..b2ed698 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 1a3bdc2..42f43fa 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 8a4863c..d79eeda 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 a73ecf5..2133223 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 2af4006..381b22e 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 86d1c8e..eedc399 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 1059146..89c7f32 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 0c4880a..bcaf4ab 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 b26f519..73de405 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 8a5b576..ea8714f 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
index bad16d3..6aaaeb3 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 10c2e41..991c26a 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 e750e9c..f056b4f 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 4cbf601..deedc0d 100644 (file)
@@ -3123,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
@@ -3790,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
index 3cad7db..baee3d4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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
@@ -1131,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
 #
@@ -1150,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
@@ -1224,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  ''
@@ -1411,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 b0fabfa..364c6da 100644 (file)
@@ -59,6 +59,24 @@ config HAVE_KPROBES
 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
 
index 32ca1b9..6e94313 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 40c15e7..234e42b 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 d8c4cea..a13de49 100644 (file)
@@ -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 dabb015..c8f5282 100644 (file)
@@ -314,7 +314,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.
@@ -325,7 +325,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.
 
@@ -418,7 +418,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
 
index b20995a..2f07477 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 dd29473..69130f3 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 c3c3a33..8557965 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 0a8e1ff..f6d3fdd 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 493ecee..2307587 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 747b9de..dc8b407 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 de19bee..8ced9bc 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 86cba4a..cae5f52 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 ec18913..483d436 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 8a81f76..9762b15 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 ae28101..5f30948 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 b22a1a0..af2c33a 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 8a2a958..117cf6c 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 dab958d..02a70b2 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 cb065fe..082ed59 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 8f76af5..57a6221 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 4d1d9c7..6a68079 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 08382c0..43dfbd0 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 b4cd5d0..6605a09 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 b6a70fc..66e77bb 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 78a5cdb..ca87587 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 1d7bca6..5fed576 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 e6695c4..e1b1f02 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 81cdc82..daf2807 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 5fea5a1..df16a4e 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 f0f70ba..896ff9f 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 3f86769..c6e044b 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 3781b3d..3947c50 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 ad2e5b9..be4f4a2 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 9db7e1f..926d15f 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 f19f3f6..ca12a9c 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 6abf568..afd1dc1 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 49dec78..2096070 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 4087960..7d9bb4d 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 d1e75b7..37d9f2e 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 b8ebaf4..1088426 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 04661fe..4429b84 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 6588f2c..0f00fea 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 4c3ab43..0b06941 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 fd7537f..99d4fb1 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 845c663..41f94f6 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 e020c27..34389b6 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 5c00b3f..8948d45 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 0cf62ef..d963125 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 620fa0f..870b349 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 88405e7..40a0bee 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 e2a0084..9ae3f6d 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 10ae628..2a46d27 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 a9cef97..f270ada 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 968d0b0..5ed67e1 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 bcf0cde..31f5bd4 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 cc1c4fa..8d1ab54 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 ac26423..af7375b 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 851ec2d..c8e38b5 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 34cd585..23e9b92 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 dee7bf3..12811b7 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 31afe50..56d3ee0 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 8473c37..b34ff42 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 fa0403a..c5e438b 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 9f1ed15..967a484 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 c7bf7e0..69a71f1 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 fbfa260..a8ec97b 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))
@@ -55,15 +55,19 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long 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 4a77367..318b268 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 d8e9c2c..63e0943 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) {
index 5e28c21..0af3872 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 60f162d..8c5e656 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 ae2c5d7..001436c 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 af90b00..8dc4821 100644 (file)
@@ -18,6 +18,10 @@ config BOARD_ATSTK1004
        bool "ATSTK1004"
        select CPU_AT32AP7002
 
+config BOARD_ATSTK1006
+       bool "ATSTK1006"
+       select CPU_AT32AP7000
+
 endchoice
 
 
index beead86..edecee0 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 e11659b..8538ba7 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 ea109f4..591fc73 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 c7236df..d9c5e0a 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 abd954f..7e7f327 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 604f44f..1617048 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 */
 
@@ -1871,6 +1871,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
  * -------------------------------------------------------------------- */
 static struct resource atmel_ac97c0_resource[] __initdata = {
@@ -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 fa427ed..b2d9bc6 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 3c85fda..fa92ff6 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
  *
index b83b8ef..5a097c4 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 c61bdeb..c468624 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 3cbe16c..9564731 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 5e6fb9d..66854a8 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,8 +925,36 @@ 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
@@ -881,9 +962,99 @@ CONFIG_SSB_POSSIBLE=y
 # 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 8d817ba..6bc11db 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
@@ -862,10 +782,6 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_TEST is not set
 
 #
-# I2C RTC drivers
-#
-
-#
 # SPI RTC drivers
 #
 # CONFIG_RTC_DRV_RS5C348 is not set
@@ -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 20d598d..d77d991 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
 
 #
@@ -941,6 +898,10 @@ CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_MPU401 is not set
 
 #
+# SPI devices
+#
+
+#
 # ALSA Blackfin devices
 #
 CONFIG_SND_BLACKFIN_AD1836=m
@@ -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 b5189c8..5fd7c4b 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
 
 #
@@ -993,6 +959,10 @@ CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_MPU401 is not set
 
 #
+# SPI devices
+#
+
+#
 # ALSA Blackfin devices
 #
 CONFIG_SND_BLACKFIN_AD1836=m
@@ -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 1ff2ff4..390669e 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 b4a20c8..976a4d7 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,9 +361,15 @@ 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
 #
 CONFIG_NET=y
@@ -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 560890f..09deea4 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 9f66d2d..219fc34 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 2694d06..9873d58 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 9020725..0e3605f 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 daf0090..59c7cdb 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 679c748..ba0bee9 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 4384a67..285d224 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 87622ad..bffca7d 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 951ea04..b1309f8 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 6140cd6..606adc7 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 d54f190..93229b3 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 b6d89d1..ecbd141 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 2788532..ecbabc0 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 6be0c50..224e7cc 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 65f4e67..31bd9bf 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 a9c1551..a1f9641 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 14a4284..e1bebc8 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 f51ab08..bf1a51d 100644 (file)
@@ -220,6 +220,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                                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) {
                                memcpy(&tmp, (const void *)(addr + add), sizeof(tmp));
@@ -290,6 +304,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long 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) {
                                memcpy((void *)(addr + add), &data, sizeof(data));
index 8efea00..23e637e 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 f061f51..ad922ab 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 3ecc64c..0896e38 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,14 +187,13 @@ 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 6a570ad..8bf9e58 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 7277d35..7ba7d25 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 57bdb3b..fe05cc1 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 1295dea..c671e85 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 671f9d6..6dbc76f 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 48cd58a..6b019ea 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 af7c211..166fa22 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 f719114..06b9178 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 5b8bd40..cf1a2df 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 caaab49..f9160d8 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 b7981d3..5e3f1d8 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 038f70e..eceb484 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 f5fd768..64d7461 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 0be805c..4fe6a23 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 3246f91..5af3c31 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;
@@ -273,6 +367,11 @@ int sram_free(const void *addr)
                 && 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 0fb73b7..8cb0945 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 ec3141f..bc240ab 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 a3ca551..6fea45f 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 4e2e2e2..8bd5a5b 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 5b06ffa..2fdd212 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 48a0393..7ca8a6b 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 9af7740..1b851db 100644 (file)
@@ -63,37 +63,6 @@ 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
  * was begun by the code in arch/head.S.
  * The parameters are pointers to where to stick the starting and ending
index e4f4199..a1d228f 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 1c44ec2..88b6e6f 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 34421ae..4956be4 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 19d4493..fc8f350 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 2672f4d..7a37d06 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 52175af..53ebb64 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 2554eb5..24d429f 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.
  */
index 79f5f94..81bb08c 100644 (file)
@@ -69,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 22e2a0d..3bf249c 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 4873102..44e8dd8 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 ae39dd8..891312f 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 21891c7..54be6af 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 a477038..baffc58 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 be255eb..18072e0 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;
 }
index fe88418..587da5e 100644 (file)
@@ -117,6 +117,7 @@ config PPC
        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
index 81c8324..1cbbf70 100644 (file)
@@ -148,7 +148,7 @@ transfer_to_handler:
        /* Check to see if the dbcr0 register is set up to debug.  Use the
           internal debug mode bit to do this. */
        lwz     r12,THREAD_DBCR0(r12)
-       andis.  r12,r12,(DBCR0_IDM  | DBSR_DAC1R | DBSR_DAC1W)@h
+       andis.  r12,r12,DBCR0_IDM@h
        beq+    3f
        /* From user and task is ptraced - load up global dbcr0 */
        li      r12,-1                  /* clear all pending debug events */
@@ -292,7 +292,7 @@ syscall_exit_cont:
        /* If the process has its own DBCR0 value, load it up.  The internal
           debug mode bit tells us that dbcr0 should be loaded. */
        lwz     r0,THREAD+THREAD_DBCR0(r2)
-       andis.  r10,r0,(DBCR0_IDM  | DBSR_DAC1R | DBSR_DAC1W)@h
+       andis.  r10,r0,DBCR0_IDM@h
        bnel-   load_dbcr0
 #endif
 #ifdef CONFIG_44x
@@ -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)
@@ -720,7 +725,7 @@ restore_user:
        /* Check whether this process has its own DBCR0 value.  The internal
           debug mode bit tells us that dbcr0 should be loaded. */
        lwz     r0,THREAD+THREAD_DBCR0(r2)
-       andis.  r10,r0,(DBCR0_IDM  | DBSR_DAC1R | DBSR_DAC1W)@h
+       andis.  r10,r0,DBCR0_IDM@h
        bnel-   load_dbcr0
 #endif
 
@@ -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 d736924..2d802e9 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 4d96e1d..9ddfaef 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 29a0e03..aab7688 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 db2497c..e030f3b 100644 (file)
@@ -254,7 +254,7 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
                return;
 
        /* Clear the DAC and struct entries.  One shot trigger */
-#if (defined(CONFIG_44x) || defined(CONFIG_BOOKE))
+#if defined(CONFIG_BOOKE)
        mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W
                                                        | DBCR0_IDM));
 #endif
@@ -286,7 +286,7 @@ int set_dabr(unsigned long dabr)
        mtspr(SPRN_DABR, dabr);
 #endif
 
-#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
+#if defined(CONFIG_BOOKE)
        mtspr(SPRN_DAC1, dabr);
 #endif
 
@@ -373,7 +373,7 @@ 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_44x) || defined(CONFIG_BOOKE)
+#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);
@@ -568,7 +568,7 @@ void flush_thread(void)
                current->thread.dabr = 0;
                set_dabr(0);
 
-#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
+#if defined(CONFIG_BOOKE)
                current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W);
 #endif
        }
index c4ab219..b72849a 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
@@ -1339,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);
@@ -1386,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
@@ -1395,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);
 
@@ -1431,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 a5d0e78..6b66cd8 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>
@@ -717,7 +718,7 @@ void user_disable_single_step(struct task_struct *task)
        struct pt_regs *regs = task->thread.regs;
 
 
-#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
+#if defined(CONFIG_BOOKE)
        /* If DAC then do not single step, skip */
        if (task->thread.dabr)
                return;
@@ -744,10 +745,11 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
        if (addr > 0)
                return -EINVAL;
 
+       /* The bottom 3 bits in dabr are flags */
        if ((data & ~0x7UL) >= TASK_SIZE)
                return -EIO;
 
-#ifdef CONFIG_PPC64
+#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
@@ -769,7 +771,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
        task->thread.dabr = data;
 
 #endif
-#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
+#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
@@ -1013,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
@@ -1055,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 09ded5c..149cb11 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 61a3f41..9cc5a52 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 04d8de9..8b25f51 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 7aada78..a54405e 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;
@@ -147,7 +147,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
         */
        if (current->thread.dabr) {
                set_dabr(current->thread.dabr);
-#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
+#if defined(CONFIG_BOOKE)
                mtspr(SPRN_DBCR0, current->thread.dbcr0);
 #endif
        }
@@ -177,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 f5ae9fa..5337ca7 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 f258964..b0dbb1d 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 800e5e9..56d172d 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 */
 
index ade8aea..22a3c33 100644 (file)
@@ -530,7 +530,7 @@ static dma_addr_t vio_dma_iommu_map_single(struct device *dev, void *vaddr,
        }
 
        ret = dma_iommu_ops.map_single(dev, vaddr, size, direction, attrs);
-       if (unlikely(dma_mapping_error(ret))) {
+       if (unlikely(dma_mapping_error(dev, ret))) {
                vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
                atomic_inc(&viodev->cmo.allocs_failed);
        }
@@ -1031,8 +1031,8 @@ 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() {}
-static void vio_cmo_sysfs_init() { }
+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);
index 75dff7c..5a5602d 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 0000974..8c605d0 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 fb42c4d..f1c2d55 100644 (file)
@@ -113,7 +113,7 @@ static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr,
 static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
                           unsigned long address, unsigned int psize)
 {
-       pte_t *new = kmem_cache_alloc(huge_pgtable_cache(psize),
+       pte_t *new = kmem_cache_zalloc(huge_pgtable_cache(psize),
                                      GFP_KERNEL|__GFP_REPEAT);
 
        if (! new)
@@ -730,25 +730,27 @@ 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;
+
        /* 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_64K);
        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(
@@ -756,7 +758,7 @@ static int __init hugetlbpage_init(void)
                                                HUGEPTE_TABLE_SIZE(psize),
                                                HUGEPTE_TABLE_SIZE(psize),
                                                0,
-                                               zero_ctor);
+                                               NULL);
                        if (!huge_pgtable_cache(psize))
                                panic("hugetlbpage_init(): could not create %s"\
                                      "\n", HUGEPTE_CACHE_NAME(psize));
index a41bc5a..4f7df85 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] = {
@@ -163,19 +168,8 @@ struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
 
 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 1ca2235..702691c 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 0e04f8f..3e7e0f1 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 418b605..5122ec1 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 7123472..690ca7b 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 1dc7295..731d7b1 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 3163544..88ccf3a 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 47de4d3..572771f 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 c6b3be0..38fe32a 100644 (file)
@@ -289,7 +289,9 @@ static int cmm_thread(void *dummy)
 }
 
 #define CMM_SHOW(name, format, args...)                        \
-       static ssize_t show_##name(struct sys_device *dev, char *buf)   \
+       static ssize_t show_##name(struct sys_device *dev,      \
+                                  struct sysdev_attribute *attr,       \
+                                  char *buf)                   \
        {                                                       \
                return sprintf(buf, format, ##args);            \
        }                                                       \
@@ -298,12 +300,14 @@ static int cmm_thread(void *dummy)
 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, char *buf)
+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);
index 4f82e5b..569079e 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;
 }
 
@@ -331,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;
 
index 4e0633c..ed60f3a 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 47a0b64..6123610 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 11230b0..2960702 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 1782cbc..8b00eb2 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 5a55611..1703926 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 388cc74..4993b0f 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 8879938..7bfb0d2 100644 (file)
@@ -477,6 +477,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
@@ -491,6 +495,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
@@ -498,6 +517,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
@@ -559,6 +592,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 0f45498..36f4b1f 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 fb7b1b1..c627e45 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 b3a876a..a743368 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 7703756..5f231dd 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 963c993..7bd365a 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 763f6de..1112e86 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 c9431b3..8ae718d 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 c455047..b1ec085 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 318bc8a..cf4a5ba 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 ede3957..6e228ea 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 89b4086..8b37869 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 c0d25fb..47685f6 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 912f3e2..658d4f9 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)
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 84c0075..7b72736 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,57 +235,50 @@ 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
 #
 CONFIG_NET=y
@@ -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 2dd83af..7be79cd 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,48 +248,40 @@ 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
 #
 CONFIG_NET=y
@@ -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,50 +380,55 @@ 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
 #
 
 #
 # 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 0718805..847e908 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 e1284fc..f54c291 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 ea40470..cf48b12 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 f57095a..d3839e6 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 4bbdce3..0e6905f 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 01ff4d0..d3d9f32 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 b5f1e23..f5eb56e 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 da5dae7..8c70e20 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 0fc8906..ee894e5 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 6d285af..85b0bf8 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 cc530f4..56e5878 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 7e2b90c..1ab1ecf 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 11b6d9c..dac4297 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 be49269..2e42572 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 a880e79..9381ad8 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 299138e..db91385 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,36 +543,151 @@ 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 6d4f50c..78881b4 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 f26b5cd..6851dba 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 62ebccf..de1ede9 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 a0470f2..cd6baff 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 f189a55..3c5b629 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
@@ -56,6 +57,11 @@ static struct plat_sci_port sci_platform_data[] = {
                .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 18dbbe2..fb8200c 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 621e732..30baa63 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 718bd23..5e0dd19 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 5c17de5..ec1eadc 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 921892c..3326a45 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);
index 0283d81..b9dbd2d 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 fddb547..2bc72de 100644 (file)
@@ -241,6 +241,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);
                break;
index bca2bbc..6339d0c 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 f311551..4bbbde8 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 a46cc3a..0af693e 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 d5d7843..0b436aa 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 7281342..0758b5e 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 8935570..1ca9ad4 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 e08b3bf..511a942 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 ebb55d1..8596cc7 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 5fd2184..56d0a7d 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 c5b56d5..0e189cc 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 43d7ff6..1fdc8d9 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 d3c33fc..8277982 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>
@@ -185,3 +186,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 d1fa275..0c776fd 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 d652d37..b75a7ac 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)
 {
index 8c7a9ca..38870e0 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 7f885b7..eaf2514 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 0b0ec6e..cef7276 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 1bba7d3..0a11cc0 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 375de7c..a214002 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
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 66d8166..8ff83d8 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 24c6f3c..13dc67f 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 4db8f23..e03e088 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 1a2949d..b1edd94 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 08277e6..797722c 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 2dfc07b..e179bc1 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 2b6a379..0491680 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 4e3553d..7ac0d74 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 b76fac0..b5976de 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 a2c4d51..31d48a0 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 8a1d9d6..10a0df5 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 6210a3c..467caa2 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 7483504..0f4150e 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 38cbec7..bfa64f9 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 8cc69bf..aa1d90a 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 959d6c8..cf7189c 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 9d4c024..46a8aec 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 a5da2d0..83a6d16 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 f035c45..0a2816c 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 6c628ba..faebd33 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 acdd06e..ae3f00b 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 c6a9f03..736335f 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 1564787..44d4e23 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 14652ab..be8f03f 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 67%
rename from include/asm-sparc/io.h
rename to arch/sparc/include/asm/io.h
index fc9024d..a34b299 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 91b072b..e650965 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 037605d..17d6ef7 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 7af6bb4..3b44a6a 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 c6402b1..1e13863 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 db398fb..0fca9d9 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 024fc54..bb42e59 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 fe07d00..8d12581 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 9ab65c2..67ed9e3 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 ee66bf6..88fa313 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 e14efb9..5531346 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 516138f..e82cf9a 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 5b9f7fe..433be3e 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 851eb84..aa69977 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 3833435..723f7c9 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 78aa032..4f66a5f 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 8c349f0..aaeae90 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 e88d7c0..72e04e1 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 f32f49f..f21de03 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 66%
rename from include/asm-sparc/pci.h
rename to arch/sparc/include/asm/pci.h
index b807d52..6e14fd1 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 b93b6c7..0ee949d 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 f59f257..4f79a54 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 d98ed6c..bfb1d19 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 7fa02b5..b6db1f7 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 63cdef5..59ba6f6 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 781bd46..08237fd 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 58c820d..03a0e09 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 11a66bb..9da9646 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 562c0d6..2ae67a2 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 70d4280..137a6bd 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 f36ab6c..6dcbe2e 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 0401cc7..d43c88b 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 a682e66..ec6d45c 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 cb34b0a..0c16e19 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 42fecfc..1efb056 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 eb24a07..6f277d7 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 8f29a19..f82481a 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 b1a0e31..ec21a45 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 cbd0191..c7c69b0 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 c676fcc..4ebc382 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 16fda7e..8bf0cfe 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 82fc7d5..e92de7e 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 2c9fccf..bd81f8d 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 36f5f9e..27ab05d 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 1f9dedf..b59672d 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 3b71c50..f276b00 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 9fdcaf8..d815301 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 a70cc52..5e937a7 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 14c04c7..98b72a0 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 92ee1a8..d81a02e 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 15e2a3b..7944a7c 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 64155cf..122d7ac 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 95%
rename from include/asm-sparc/thread_info_32.h
rename to arch/sparc/include/asm/thread_info_32.h
index 2cf9db0..cbb892d 100644 (file)
@@ -130,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() */
@@ -142,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 97%
rename from include/asm-sparc/thread_info_64.h
rename to arch/sparc/include/asm/thread_info_64.h
index 960969d..c0a737d 100644 (file)
@@ -219,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 */
@@ -239,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)
@@ -250,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 475baa0..612fd27 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 01d9f19..70cc37b 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 71b45c9..b6ccdb0 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 c622535..18b30bc 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 a821057..92d0393 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 6e6bc12..2c9629f 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 ed13630..ee4f191 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 424facc..e88fbe5 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 3c26096..4207fb3 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 97%
rename from include/asm-sparc/utrap.h
rename to arch/sparc/include/asm/utrap.h
index 9da37ba..b10e527 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 a22fed5..541e137 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 35089a8..8ed591c 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 f34b2cf..44bfa07 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 a023388..bee4bf4 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 2f96256..e8cdf71 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 81f3b92..20699c7 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 891f460..4da2e1f 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 3fd1df9..c94f91c 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 7c88263..923a989 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 c197948..c831b0a 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 32fbab6..fc294a2 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 f6c9fc9..bd578cc 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 c6fc695..97a993c 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 9667e96..d1b8445 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 97cdd1b..ba5b09a 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 db19ed6..a2f2427 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 7132974..4e821b3 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)
index e2274ef..61d7e61 100644 (file)
@@ -264,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 e3cba0b..b6fa287 100644 (file)
@@ -22,8 +22,9 @@ config X86
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_IOREMAP_PROT
+       select HAVE_GET_USER_PAGES_FAST
        select HAVE_KPROBES
-       select ARCH_WANT_OPTIONAL_GPIOLIB if !X86_RDC321X
+       select ARCH_WANT_OPTIONAL_GPIOLIB
        select HAVE_KRETPROBES
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FTRACE
@@ -332,20 +333,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
@@ -369,6 +356,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"
@@ -1279,6 +1276,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 919ce21..f5631da 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 58cccb6..a0e1dbe 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 79eff73..22d7d05 100644 (file)
@@ -664,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;
@@ -1082,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 c9d8ff2..d9a9da5 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 f67e934..a7010c3 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 8864230..9fe478d 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 9dd9262..c43caa3 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 19e7fc7..b67a4b1 100644 (file)
@@ -37,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>
@@ -413,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)
 {
@@ -439,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));
 
@@ -477,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;
@@ -486,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,
@@ -500,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);
 }
@@ -525,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;
@@ -544,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,
@@ -1241,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:
@@ -1262,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;
@@ -1503,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;
 
@@ -1519,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)
@@ -1532,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 cbecb05..3754412 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;
@@ -312,6 +312,8 @@ static int dma_release_coherent(struct device *dev, int order, void *vaddr)
 
 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 +321,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 +369,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;
@@ -435,8 +438,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 +451,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 +480,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))
                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 c982404..49285f8 100644 (file)
@@ -689,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 792b917..3f91f71 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 20df839..c4ce033 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 c30fe25..703310a 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 b0e4ddc..2fa2319 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 b756e87..e2ee264 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 0cac637..2a69773 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 9f1cdb0..5916191 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 1fbb844..2977ea3 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
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c
new file mode 100644 (file)
index 0000000..3085f25
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * 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 end = start + (nr_pages << PAGE_SHIFT);
+       unsigned long addr = start;
+       unsigned long next;
+       pgd_t *pgdp;
+       int nr = 0;
+
+       if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
+                                       start, nr_pages*PAGE_SIZE)))
+               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 ec37121..129618c 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 b4becbf..cab0abb 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 81d0560..34163cf 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 9735acb..cf4eb0e 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 ddd96fb..af37e4a 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 d592dbb..283c08f 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 de8d186..2014253 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 7d5c63c..068aa1c 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 d222239..efd5775 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 855ed1a..af0d175 100644 (file)
@@ -103,7 +103,8 @@ static ssize_t show_mem_phys_index(struct sys_device *dev,
 /*
  * Show whether the section of memory is likely to be hot-removable
  */
-static ssize_t show_mem_removable(struct sys_device *dev, char *buf)
+static ssize_t show_mem_removable(struct sys_device *dev,
+                       struct sysdev_attribute *attr, char *buf)
 {
        unsigned long start_pfn;
        int ret;
@@ -204,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;
        }
 
index 40fc14f..75dd6e2 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 19b8850..ca7c72a 100644 (file)
@@ -304,9 +304,9 @@ static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t co
 }
 
 static long dsp56k_ioctl(struct file *file, unsigned int cmd,
-                                                       unsigned long arg)
+                        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)
index 27fdc08..8a2fce0 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 f9f72a2..006be92 100644 (file)
@@ -125,15 +125,15 @@ static ssize_t flash_read(struct file *file, char __user *buf, size_t size,
        ssize_t ret;
 
        if (flashdebug)
-               printk(KERN_DEBUG "flash_read: flash_read: offset=0x%lX, "
-                      "buffer=%p, count=0x%X.\n", p, buf, count);
+               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;
 
-       ret = simple_read_from_buffer(buf, size, ppos, FLASH_BASE, gbFlashSize);
+       ret = simple_read_from_buffer(buf, size, ppos, (void *)FLASH_BASE, gbFlashSize);
        mutex_unlock(&nwflash_mutex);
 
        return ret;
index 929101e..7d500f8 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 19ce5eb..90a8590 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 cc7dcea..5eca7a9 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 1bfdcc8..0e0363a 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 fe914d3..590762a 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 ccacd26..561f765 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 42f3815..b141450 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 dbefbb3..d9799e2 100644 (file)
@@ -144,6 +144,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
                        size_t count, loff_t *ppos);
 
 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);
@@ -235,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,
@@ -1303,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 4ba3aec..7b0c352 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 e1fc193..ae766d8 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 60a2d26..68f052b 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 c7a977b..ed1879c 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 69c5afe..1718b3c 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 5405769..5ce07b5 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 b11943d..681c15f 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 76f2671..fa6d6ab 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 da873d7..bbd73a4 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 c639915..bc81d6f 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 bcbe794..e14c03d 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 333b125..251416f 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 53fc5a6..aaff50e 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 213b0ff..c1b8107 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 40db807..e5d1a0b 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 e23399c..001622e 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 5641387..452c2d8 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 48d084b..3c855ff 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 79b455a..32104ea 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 007390a..4864723 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 9494005..e603736 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 195f973..b41dd26 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 eaba032..284c9bc 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 86e0169..82d9a0b 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 0b191a4..a146457 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 38d6907..a3c2851 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 d26a913..6e2b0dc 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
index db2086f..a4cdb46 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 02a99bc..f7bc7dd 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 12d6bc6..d425652 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 e2d11be..13beede 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 4e36aa7..cc6858f 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 d2884e7..b0cab64 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 6aa531d..9f0b964 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;
 }
@@ -229,46 +248,12 @@ 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 7717cb2..367b3d2 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 85f26d1..1513d40 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 e3939d1..d79942e 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 691525c..9d9a9dc 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 8486abc..c600ab7 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 2bcfa0b..223d56d 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 78f2abb..2f12d60 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);
@@ -620,14 +626,30 @@ static void serio_destroy_port(struct serio *serio)
 }
 
 /*
+ * 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 e573665..6e60a97 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 39a804c..15cf290 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 907a45f..ce6f48c 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 4e9d8ee..d0e13fc 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 a79f029..590a137 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 66f946a..3d113c6 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 988142c..8380a45 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 11c8a18..a5d8fce 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 c0b4db2..1925118 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)
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 fea966d..71dd65a 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 171afe7..cf6a817 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 a5e6275..e8bc7ab 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 850d568..6f92bea 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 55f7e67..4dfbe5b 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 fbcb282..35b763a 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 a0545ba..72abf0b 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 266c255..597e47f 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 7588db1..7e9c090 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 a577c0f..e84152b 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 44c11e4..e206f1e 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 adfd4fc..2f408d2 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 e5238b3..029b437 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 c20553c..574dffe 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 a89dc0f..028da55 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 1360403..a9653c6 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 b4b8ed7..c5f45fe 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 6f9c185..229274a 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 87c973a..41b5a98 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 a23cc0a..d5f48a3 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 4e3f83e..1ed88f3 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 09fe6f1..7fd7ee2 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 1ec18ed..eba9209 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 46cdb54..3fe5504 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 b14db53..6166e72 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 de49be9..36e754e 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 81f6aeb..2b1a622 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 bddd3c4..0ada1c6 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 0133ecf..43c7549 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 0708021..e2dde08 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 66e052f..bb5d92f 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 b0ccf7c..6290553 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 dc93a88..a4984ff 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 acc3208..cefa44f 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 4ebdfba..d70172d 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 18f2abd..f8d62cf 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 43773c5..9f17a33 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 f606d29..d4a6e56 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 45d5db5..bbc6f8b 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 8c7d195..56ebfd5 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 52b2491..ed9a50f 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 898e123..443e590 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 e26f54a..c37f5fd 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 c6d4705..584a83a 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 24a34fc..ce71e8e 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 0ea559a..85bf31a 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 0af5868..649682a 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 68f28e5..6819e21 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 b364ada..d3b3268 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 fe1e67b..fe9379b 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 d99453f..c149b7d 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 54de0cd..bd5d9de 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 2a81376..dc8cc61 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 5096058..8f0cfee 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 f2e8b1c..af8b9ec 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 7ce2789..515c8b5 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 1c3fa3a..61d14d2 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 645b339..e30a589 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 9aefdc5..ef48565 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 c40a286..0b55837 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 45e31b0..4801bc7 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 2d630d9..78fadd2 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 0d74e59..a7f8396 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 1728b1d..0da57f5 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 5cfb46b..e60bd31 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 e7ef093..8118091 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 fd7112c..a19de85 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 d17343e..6286a9c 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 043fc4e..ad2235d 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 448f4cd..de515da 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 e7bf4f4..209d3bc 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 72916ba..b87337e 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 10e20d8..9dd7bdf 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 bfdca58..9a1374a 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 fa6d398..de199a2 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 60eeda3..d656fec 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 0fed5cd..ef4d56e 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 14ac173..54fe650 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 05f0d5a..476ae44 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 cc61cfb..4b992bc 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 2d9f14d..49ab062 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 89842c5..9a33107 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 15d037a..2d170d1 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 013d593..44b0bff 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 8ab4ea7..c8c2f02 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 16e367c..3a051c9 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 88c2b02..21c4ee5 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 08d99c3..83139ef 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 fa7abc4..7ef18d5 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 5c052e3..ea3d702 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 dbeebe8..e18748c 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 3e68b99..33a3df1 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 1562061..17fe2c2 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 50e929d..51a3c34 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 ddea6e1..3c2be80 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 143203c..6fe715c 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 d8cd938..b608a27 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 b659bd0..a261745 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 c78ee0d..16219cf 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 abd7bef..54efa48 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 00f47e4..91b555c 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 0b79389..1ff8ba2 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 fcf2c9e..a422175 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 b761b11..22a994c 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 5d7ee8f..0069898 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 41fd792..aea1664 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 a08bb33..ab287b4 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 52e00a7..6103030 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 f8883b4..54d2023 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 39bf6b1..89a781c 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 2fb5854..7c8ef6a 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 5691e01..3da74dc 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 1622f70..846a14a 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 ee43499..554d229 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 eafb0c7..9edaca4 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 1010e51..baded12 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 36047d4..e69de29 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 e21b573..e69de29 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 51b1461..00425d7 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 4482b2c..19eb274 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 6180129..d657e53 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 5d036e7..88e1751 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 e23ce1d..cb3a33e 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 b58369e..614755e 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 a5217a2..f051c6a 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 9d3c18b..e600576 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 0d72dc4..00306fa 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 423fa7c..9aee7cb 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 8e8e5b2..7417875 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 04eb2c3..b1d09d8 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 03e7721..6ee63e6 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 fde99d9..0d63973 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 83f076a..7021bbf 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 6893f99..98364d1 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 cfee84e..75d6184 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 2a5ab95..c0c5d75 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 1a51375..68c2689 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 6927cbe..a0884f6 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 2220f95..af60ede 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 cd4b635..e69de29 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 1cd6293..f481277 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 835ef87..2ce685d 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 012005e..f7ca3cb 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 0c8d87d..cbfc444 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 7f9c7bc..2340876 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 e39b98f..b6be5ee 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 f308c38..ad36af3 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 c109511..276bded 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 d7f130b..56dc3d6 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 ae75c18..4963d42 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 7a8ce8f..792f0b0 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 9220378..281065b 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 93d879d..d806a35 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 9da0e18..bcc32fa 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 6a3af10..28af5ce 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 4128ee2..bf1bc2f 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 051775d..c66985b 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 40d053e..b779245 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 abf6854..c317ed7 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 cd6c41d..b977116 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 3ae9551..626f4ad 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 f2b2983..b3c4d75 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 b5a11eb..d7bd71b 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/atomic.h>
 
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include "uvcvideo.h"
 
index a0f6c60..79937d1 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 e9dd996..88ca131 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 03f20ac..31944b1 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 a868b7e..be65a2f 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 6616e65..e69de29 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 01ea99c..3989b0e 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 059b01c..3518af0 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 cbecb3c..577956c 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 33f7026..9402f40 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 8405224..168baab 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 3c95316..30032e1 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 7be47a2..95c79ad 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 c2ab70a..48df661 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 7bbab54..b1b5cce 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 e5c4e9f..550ce7b 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 0929edb..d842a7c 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 1b5c417..e4dc9d2 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 c067592..ec6f596 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 485df2e..18d1c4b 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 61b98c3..a380050 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 477d0fb..44b1817 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 4e3bfbc..3485c63 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 8577de4..d32d6ad 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 241592a..3f15fcf 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 34402c4..d6a0074 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 a592042..f5233f3 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 b36cae9..c3c24fd 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 d709d92..a1abf95 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 b1147aa..12b7325 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 d142b6b..9f9354f 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 3b870e7..c6408a6 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 2d87501..94e55e8 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);
 }
index 321eb91..f5ade19 100644 (file)
@@ -360,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---
index e171650..bf5e4d0 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 19a1a25..889e5f8 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 fd95b18..0d9b2d6 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 cdb332b..c819eff 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 1d795c5..6da80fd 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 a9a5657..26bd80e 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 cce873c..992b4be 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 5e880c0..f61406d 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 41cc633..7503b81 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 c3a5db7..5f95e10 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 a06bf8b..e354fae 100644 (file)
@@ -9,6 +9,8 @@
  * your option) any later version.
  */
 
+#include <linux/scatterlist.h>
+
 /*
  * Controller registers
  */
index eed06d0..14f11f8 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 52d51eb..d072ca5 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 fcd1aec..5f1b472 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 f7fcc63..a972cc6 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 1b720cc..d4714dd 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 a4463a9..c418e92 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 72e0022..0ee4570 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 2174c97..c857609 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 d338b8c..f061885 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 aa07575..dbba5ab 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 */
@@ -522,6 +537,36 @@ static const struct amd_flash_info jedec_table[] = {
                        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,
                .name           = "Atmel AT49BV512",
@@ -599,6 +644,36 @@ static const struct amd_flash_info jedec_table[] = {
                        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,
                .name           = "Fujitsu 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 fc478c0..494d30d 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 5cb6d52..072dd8a 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 cb27f85..821d0ed 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 e472a0e..71bc07f 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 35ed110..9c613f0 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 0f788d5..0993d5c 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 7b72a1b..91fbba7 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 846989f..50de839 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 6413efc..e32c568 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 83be346..d853f89 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 fd8a8da..874e51b 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 d8cc94e..6e62922 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 1d324e5..f4bda4c 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 b402269..b35c333 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 9cff119..6a9a24a 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 8a6eef7..04deafd 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 b35e481..54e36bf 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 0399be1..3aaca88 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 c7987b1..088fbb7 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 bc99817..d38bca6 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 cb86db7..a425d09 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 5c29872..f34f20c 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 b0e3965..c4f9d33 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 c551d2f..9113628 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 d2fbc29..df8e00b 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 c6ce867..6cda6df 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 728aed6..948b86f 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 7ed3424..cf32267 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 9f17bb6..cb507da 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 629e6e2..6464d48 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 65e5ee5..0ecc3f6 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 92a9c7f..e115667 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 b32bb93..3aa018c 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 1c3b34a..0713e3a 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 e0558b0..d171674 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 1488bb9..d92b7c7 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 1c5b97c..9433738 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 7c50c27..a8e3fde 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 6dde318..ef89154 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 2c884c4..aeb6c91 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 a0b4dc7..2682ab5 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 325c888..ee361aa 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 f27c132..a806119 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 c8396b8..c226479 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 01f19a4..9c7a5fb 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 67620ad..9e05450 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 9105e6c..3f26837 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 06b1187..706f673 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 95dcab2..c0cb319 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 0c9b305..965e6c6 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 a6642db..43e04c1 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 e6e391e..0a60ebb 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 d2ab1ba..5c6a25c 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 0cc3167..90924fb 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 183255f..42d844f 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 3eb2643..e7dd9c8 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 4d858b3..de002eb 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 809a0c8..14d90ed 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 c7d5a52..e177a43 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 b8c1331..6e1e99c 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 7cc4041..1b1c0b7 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 4045e37..85c1e56 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 0fc5584..21169e6 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 5e2bce2..b5391eb 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 917dc77..026eab0 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 d76ceef..0eb41d9 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 001af7f..0d7c883 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 5217340..a5d3d85 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 b47270e..e2147bf 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 0f915ac..77a8bfc 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 3fcf921..0dc645f 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 $
  */
 
 /****************************************************************************/
index b3e4873..5a0c9a3 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 ca93212..e243476 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 ac5b810..413b0cf 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 839eed8..9ff007c 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 952da30..208c6fa 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 f79dbb4..852165f 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 aef9f4b..d2f3318 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 d563dcd..2972a5e 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 f7e7890..a9d2469 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 07c7011..edb90b5 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 5076faf..71406e5 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 a6e74a4..d772581 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 0adb287..99aec46 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 09e421a..761946e 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 dd38011..553dd7e 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 da6ceaa..95345d0 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 0e72153..765d4f0 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 ba67bbe..387e435 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 bed8729..ced14b5 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 4b69aac..9dff513 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 2d585d2..9e59de5 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 ba1bdf7..d1129ba 100644 (file)
@@ -798,6 +798,87 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
+ * 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
  * @chip:      nand chip 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 5e121ce..0b1c485 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 9003a13..918a806 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 a3e3ab0..69ee2c9 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 bb885d1..ecd70e2 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 082073a..cc86584 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 26f8821..a033c4c 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 b34a460..556139e 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 033f880..6dba2fb 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 1f6d429..0cc6d0a 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 f9e2d4a..bbf492e 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 f400810..807a727 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 0c9ce19..320b929 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 345e6ef..ccc4f20 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 5d7965f..926cf3a 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 c5030f9..2d600a1 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 c84e454..e538c0a 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 7a14980..18d3eeb 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 0263bef..af251a5 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 83768df..f1936d5 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 a96331c..1b0861d 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 1037b13..19d32a2 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 a14561f..9350564 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 9c0f56b..d136778 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++;
index e5a6e2e..a03fe1f 100644 (file)
@@ -260,7 +260,7 @@ 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(dma_addr))
+               if (dma_mapping_error(&adapter->vdev->dev, dma_addr))
                        goto failure;
 
                pool->free_map[free_index] = IBM_VETH_INVALID_MAP;
@@ -294,7 +294,7 @@ failure:
                pool->consumer_index = pool->size - 1;
        else
                pool->consumer_index--;
-       if (!dma_mapping_error(dma_addr))
+       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);
@@ -448,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;
                }
@@ -461,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;
                }
@@ -472,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);
@@ -489,7 +488,7 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
                                                 &adapter->rx_buff_pool[i]);
 
        if (adapter->bounce_buffer != NULL) {
-               if (!dma_mapping_error(adapter->bounce_buffer_dma)) {
+               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,
@@ -535,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");
 
@@ -563,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);
@@ -645,7 +647,7 @@ static int ibmveth_open(struct net_device *netdev)
        adapter->bounce_buffer_dma =
            dma_map_single(&adapter->vdev->dev, adapter->bounce_buffer,
                           netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL);
-       if (dma_mapping_error(adapter->bounce_buffer_dma)) {
+       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);
@@ -922,7 +924,7 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
                buf[1] = 0;
        }
 
-       if (dma_mapping_error(data_dma_addr)) {
+       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,
index b8d0639..c46864d 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 f9d6b4d..096bca5 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 aa95287..f094ee0 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 04d5bc6..2845a05 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
index 95e87a2..9bb50e3 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 ea3a09a..8a8b561 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
@@ -526,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 5727822..7e32955 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
index fbf0e22..decbb5c 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
index 2a5bef6..baf4bf6 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 6c44edf..ab56a2f 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 4a6c4d5..0e7eb10 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 8e1d24c..1252a91 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
index b4b5787..c83f88c 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 7803849..5337e3a 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
index a3c04c5..62071d9 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
index ee5484c..c49a860 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 e199715..3951b88 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 d23f46d..533eb6d 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 993d87c..edc0fd5 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 739b3ab..ddccc07 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 e7d48a3..e82b37b 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 9dae40c..86d77d0 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 601b001..0d27dd3 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 5cdd082..5e8374a 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 00aa0b1..b6435d0 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 a645e50..8487ace 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 217d506..d9769c5 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 1d7ec31..f821dbc 100644 (file)
@@ -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 548772e..4c3c6f8 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 23ffb7c..ad8ac1a 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 344e1b0..6a98dc8 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
@@ -92,11 +39,6 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
 
                info.irq = irq_of_parse_and_map(node, 0);
 
-               if (of_find_i2c_driver(node, &info) < 0) {
-                       irq_dispose_mapping(info.irq);
-                       continue;
-               }
-
                info.addr = *addr;
 
                request_module(info.type);
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 0338b09..e970594 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 802a81d..00e1d96 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 e0c2a45..8a846ad 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 d950fc3..554e11f 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 1323a43..ad27e9e 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 e9c3562..c95f77d 100644 (file)
@@ -1123,6 +1123,12 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
 }
 
 /**
+ * pci_target_state - find an appropriate low power state for a given PCI dev
+ * @dev: PCI device
+ *
+ * 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.
  */
 pci_power_t pci_target_state(struct pci_dev *dev)
 {
index b1724cf..2036300 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);
        }
 }
 
index 420a775..8c21446 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 e3fa9a2..9fd7bb9 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 a762a41..e75b060 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 55f55ed..0bdf9b8 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 4a5ec39..0815690 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 c3ad89e..cebb25e 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 3fbc3bd..a8b069c 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 38de31b..3e1d138 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 7045511..b92c19b 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 d14a947..1729a87 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 26be540..c7f0629 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 a814967..72fd504 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 8591585..218777b 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 0899cb6..b5a868d 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 2ef459e..2863a9d 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 83a7822..eb9dc31 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 4664331..ca55013 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 326765c..75d20f7 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 633ff40..d4640ef 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 a715632..4775426 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 aa2011b..3c257fe 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 2adc0f6..6707025 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 35272e9..e1d2ea0 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 ab6c21c..a518f2e 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 f2467e9..aa46b13 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 ae6be87..9c7a1f8 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 fdf34b0..b093a50 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 c4a7c06..ae560bc 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;
@@ -988,6 +994,17 @@ static void ibmvfc_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
 }
 
 /**
+ * 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:
@@ -2648,17 +2671,6 @@ static void ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt,
 }
 
 /**
- * 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
  *
@@ -2902,6 +2914,139 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt)
 }
 
 /**
+ * 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);
index 057f3c0..4bf6e37 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 20000ec..6b24b9c 100644 (file)
@@ -859,7 +859,7 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
                                            sizeof(hostdata->madapter_info),
                                            DMA_BIDIRECTIONAL);
 
-       if (dma_mapping_error(req->buffer)) {
+       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 "
@@ -1407,7 +1407,7 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
                                                    length,
                                                    DMA_BIDIRECTIONAL);
 
-       if (dma_mapping_error(host_config->buffer)) {
+       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");
index 3b9514c..2a5b29d 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 1821461..462a857 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 f97d172..c2a9a13 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 d931566..4871dd1 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 744f06d..48ee8c7 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 aefd865..3da02e4 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 39ae68a..139935a 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 601ec5b..a8e3ef3 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 6d6a76e..15e2d13 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 5b6e539..d51a2a4 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 c94da4f..1bcebbd 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 f40aa7b..50fe076 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 f62ed46..5ead128 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 70a0f11..805bb61 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 ac3b280..f680561 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 7fed353..edf9fdb 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 ef3c59c..2fb3fb5 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 5082ca3..a221b6e 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 2f75fe6..3c6ef64 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 f655ae3..8aa0bd9 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 3754ab8..37f9ba0 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 8dd88fc..7a4409a 100644 (file)
@@ -20,18 +20,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 +88,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 +162,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 +356,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 +531,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 +785,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 +817,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 +837,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 +961,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 +1047,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 +1176,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 +1250,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 +1294,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 cbef785..510ba64 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 8dd6000..6da31ba 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 9b4bebe..0b15673 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 4cb80b4..c2a4bfb 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 bbbc5a6..601a6b2 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 5489d50..d57669a 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 ec63b79..874d802 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 250d2f6..bc90d6b 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 62a3ad6..50baf6a 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 48eaa3b..7c8af7e 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 1728ab3..1bca744 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;
 }
@@ -2306,6 +2303,51 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
 }
 
 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)
 {
        uint32_t d[2], faddr;
index d058c88..676c390 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 5822dd5..88bebb1 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 36c92f9..ee6be59 100644 (file)
@@ -197,11 +197,43 @@ 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
  * @gfp_mask: allocation mask
@@ -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 01d11a0..27c633f 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 a235802..4969e4e 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 006a959..880051c 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 88d1b5f..ff5d56b 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 370c78c..ae7ed9a 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 b33e725..79f0f75 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 e4a0d2f..c6a904a 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 196fe3a..84b4879 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 b6e5610..ab3c718 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 cb92888..fe4c621 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 a272b9a..56823fd 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 f4461d3..3666093 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 0c63947..e5e7d78 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 03a3d45..95b9f06 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 4684cc7..c2bb53e 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 f308a03..3790906 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 22a6aae..98df165 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 5b04ddf..1723d71 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 c975c01..d4c1356 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 4b5f908..3c4a300 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 208e42b..3df2aae 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 eb84833..cd728df 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 e81d59d..0c71656 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 9149689..87b73e0 100644 (file)
@@ -334,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;
@@ -378,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 {
@@ -401,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 {
index b1cc148..f6f987b 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 0c452c4..067299d 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 ecca4a6..964124b 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,66 +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);
-               return NULL;
-       }
-
-       if (!spi_master_get(master))
+       proxy = spi_alloc_device(master);
+       if (!proxy)
                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;
        strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->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;
        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 54ac7be..6fb77fc 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 5e3e4e9..1f71543 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 832a5a4..cd9a2e1 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 51e26c1..32dd851 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 a11cc2f..4055dbd 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 e9ab657..d7822af 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 5d84b34..6b48780 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/device.h>
 #include <linux/efi.h>
 #include <linux/fb.h>
-#include <linux/major.h>
 
 #include <asm/fb.h>
 
index aa8c714..b790ddf 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 81dbcf5..fafd0f2 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 2b707a8..69de2fe 100644 (file)
@@ -1336,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;
index 1a9a60c..7fe5be4 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 598d35e..1664814 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 97e3bde..d387358 100644 (file)
@@ -1383,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"
index 3263084..4a551af 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 3b2178b..a1482a5 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 9e421ee..26f3b43 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 223b191..e9ec915 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 c4a5ad0..dc5ef14 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 6eac7bd..1377b12 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 d214837..3a89094 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 7102824..3cb6920 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 3bcbece..3ef5043 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 7e3faee..250d8c4 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 0051fd9..f658441 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);
index 966b73e..26c71ba 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 f1c2ea8..5f1538c 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 e8717de..02c6e62 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 70f5d3a..7109e45 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 034950c..87ee5cc 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 b11e63e..6a02126 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 8db6238..0ed57b5 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 ba4cddb..204cfd1 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 3b6ff85..655ed8d 100644 (file)
@@ -1003,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);
index 1b59b1e..80c1f95 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).
         */
index 2cb1acd..56372ec 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 fdc36bf..68be580 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 88322b0..25f1af0 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 10d8a0a..dcf37ca 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 d48caee..f958050 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");
 }
 
 /*
@@ -3272,7 +3271,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 f58e41d..6bb440b 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 cc950f6..688a2d4 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 0e9fc2b..57ecdc8 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 4ff8939..83fd40d 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 22857c6..1ec7076 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 9cfcf32..7e1cf26 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 0f327c2..409abce 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 4511b70..c621ffa 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 e8fa46c..b51d577 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 2e904bd..46e54d3 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 83f3069..5f40ed3 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 3d2580e..c591622 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 2f58dfc..830f51a 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 c21a1f5..c513654 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 106eba2..c9d1472 100644 (file)
@@ -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;
 }
@@ -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;
 }
index 3818d6a..f2584d2 100644 (file)
@@ -487,6 +487,7 @@ restart:
                                if (!cnt)
                                        break;
                        }
+                       cond_resched_lock(&dcache_lock);
                }
        }
        while (!list_empty(&tmp)) {
index 9e81add..9606ee8 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 2d3d102..724ddac 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 637018c..3962262 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 f976f30..929e48a 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 d755455..89209f0 100644 (file)
@@ -465,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;
@@ -473,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);
@@ -482,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;
@@ -830,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 6f403cf..448dfd5 100644 (file)
@@ -578,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;
 
@@ -589,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,
index d733531..567b134 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 5e55901..9696bbf 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
 #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/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>
@@ -106,11 +106,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;
 
@@ -118,7 +124,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;
 
@@ -656,38 +666,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,
@@ -1071,13 +1086,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)
@@ -1214,6 +1224,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)
index e58669e..ae8c4f8 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 0bde85b..b42cf57 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 31308a3..fd88c7b 100644 (file)
@@ -159,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 a754d18..b60bb24 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 0d1e627..42da16b 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 615788c..8ddced3 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;
 
index 3c8dab8..c7d04e1 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 26a5c1a..cd2b855 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 1cb371d..b5479b1 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 3a9ecac..3222f51 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 c672df4..8707a8c 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 23676f9..6d266d7 100644 (file)
@@ -498,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;
 
index 9679fcb..61d6251 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)
@@ -135,20 +126,20 @@ asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
        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()
@@ -189,6 +180,14 @@ out_fput:
 
 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);
 }
 
@@ -321,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 9785e36..987bf94 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 7b3887e..d8773b1 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 8308422..f45a449 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 51d0035..fd03330 100644 (file)
@@ -898,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;
@@ -927,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;
@@ -962,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 67ff2c6..2bada6b 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;
 
index 7d2f7d6..d2249f1 100644 (file)
@@ -956,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 6da0ab3..8b0806a 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 6074c25..58f9607 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 bcc668d..bb2cc30 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 990d9f4..9cda853 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 1e252df..e2c62f7 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 63a8a90..ca83199 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 dc4ec64..7e19835 100644 (file)
@@ -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 ac2ec5e..4abb104 100644 (file)
@@ -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 cc3b5e2..b085d64 100644 (file)
@@ -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);
index 3859118..e834e57 100644 (file)
@@ -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 5222345..d6ecabf 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 d256559..d9c59a7 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 f63a699..b8ae9c9 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 65077aa..2b3d182 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 dbd01d2..3f58923 100644 (file)
@@ -705,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;
 
index c36d948..b6726f6 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 fe79c25..6024942 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;
 }
 
@@ -650,11 +650,11 @@ asmlinkage long sys_inotify_init(void)
        return sys_inotify_init1(0);
 }
 
-asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
+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;
@@ -674,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);
@@ -688,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 044a254..26948a6 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 4c80404..d987137 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 0bb7f00..8ca058a 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 c0c141f..cd219ef 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 5e92034..5a98aa8 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 e217721..9d41f43 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 2cc866c..5e194a5 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 7da69ea..efd4012 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 4d84bdc..d3e5c33 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 455fa42..88475f1 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 854ff0e..c350057 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 359c091..3630718 100644 (file)
@@ -760,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 0149030..5eb259e 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;
 
index 523d737..d1d1eb8 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;
 
index 01e67dd..a7b0a0b 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 4f6f763..411728c 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 011ef0b..07e9715 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 2e5ab12..d642f0e 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 28a238d..74f92b7 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 df23f98..52daefa 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 1b94e36..9abcd2b 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 3adf8b2..f089e58 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 1955a27..c53e65f 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 f45451e..ea37c96 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 0f4481e..18060be 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 3c5550c..d020866 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 3e76f3b..4a46743 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 e48aba6..533a789 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 e8514e8..be2dd95 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 048ddca..1e27b4d 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 ccecfe5..2560b33 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 bb98d2f..52647be 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -122,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;
 }
@@ -223,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;
@@ -247,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);
@@ -274,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;
 }
@@ -425,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;
@@ -448,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)
@@ -457,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()
@@ -476,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;
@@ -498,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;
 }
@@ -535,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:
@@ -546,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;
 
@@ -561,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;
 }
@@ -590,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;
@@ -600,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);
@@ -612,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;
 }
@@ -653,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;
@@ -680,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;
 }
@@ -706,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;
 
@@ -714,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;
 }
@@ -982,7 +972,6 @@ int get_unused_fd_flags(int flags)
        int fd, error;
        struct fdtable *fdt;
 
-       error = -EMFILE;
        spin_lock(&files->file_lock);
 
 repeat:
@@ -990,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)
@@ -1007,7 +989,6 @@ repeat:
                 * If we needed to expand the fs array we
                 * might have blocked - try again.
                 */
-               error = -EMFILE;
                goto repeat;
        }
 
index d17b4fd..9f5b054 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 10c4e9a..fcba654 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,
@@ -978,7 +943,7 @@ struct file *create_write_pipe(int flags)
        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;
@@ -1020,7 +985,7 @@ struct file *create_read_pipe(struct file *wrf, int flags)
 
        f->f_pos = 0;
        f->f_flags = O_RDONLY | (flags & O_NONBLOCK);
-       f->f_op = &read_pipe_fops;
+       f->f_op = &read_pipefifo_fops;
        f->f_mode = FMODE_READ;
        f->f_version = 0;
 
index 797d775..0d6eb33 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 a891fe4..01ed610 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;
 
@@ -2378,53 +2403,18 @@ static int proc_base_fill_cache(struct file *filp, void *dirent,
 #ifdef CONFIG_TASK_IO_ACCOUNTING
 static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
 {
-       u64 rchar, wchar, syscr, syscw;
-       struct task_io_accounting ioac;
-
-       if (!whole) {
-               rchar = task->rchar;
-               wchar = task->wchar;
-               syscr = task->syscr;
-               syscw = task->syscw;
-               memcpy(&ioac, &task->ioac, sizeof(ioac));
-       } else {
-               unsigned long flags;
-               struct task_struct *t = task;
-               rchar = wchar = syscr = syscw = 0;
-               memset(&ioac, 0, sizeof(ioac));
-
-               rcu_read_lock();
-               do {
-                       rchar += t->rchar;
-                       wchar += t->wchar;
-                       syscr += t->syscr;
-                       syscw += t->syscw;
-
-                       ioac.read_bytes += t->ioac.read_bytes;
-                       ioac.write_bytes += t->ioac.write_bytes;
-                       ioac.cancelled_write_bytes +=
-                                       t->ioac.cancelled_write_bytes;
-                       t = next_thread(t);
-               } while (t != task);
-               rcu_read_unlock();
-
-               if (lock_task_sighand(task, &flags)) {
-                       struct signal_struct *sig = task->signal;
+       struct task_io_accounting acct = task->ioac;
+       unsigned long flags;
 
-                       rchar += sig->rchar;
-                       wchar += sig->wchar;
-                       syscr += sig->syscr;
-                       syscw += sig->syscw;
+       if (whole && lock_task_sighand(task, &flags)) {
+               struct task_struct *t = task;
 
-                       ioac.read_bytes += sig->ioac.read_bytes;
-                       ioac.write_bytes += sig->ioac.write_bytes;
-                       ioac.cancelled_write_bytes +=
-                                       sig->ioac.cancelled_write_bytes;
+               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);
-               }
+               unlock_task_sighand(task, &flags);
        }
-
        return sprintf(buffer,
                        "rchar: %llu\n"
                        "wchar: %llu\n"
@@ -2433,13 +2423,10 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
                        "read_bytes: %llu\n"
                        "write_bytes: %llu\n"
                        "cancelled_write_bytes: %llu\n",
-                       (unsigned long long)rchar,
-                       (unsigned long long)wchar,
-                       (unsigned long long)syscr,
-                       (unsigned long long)syscw,
-                       (unsigned long long)ioac.read_bytes,
-                       (unsigned long long)ioac.write_bytes,
-                       (unsigned long long)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)
@@ -2473,6 +2460,9 @@ static const struct pid_entry tgid_base_stuff[] = {
 #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),
        ONE("statm",      S_IRUGO, pid_statm),
@@ -2805,6 +2795,9 @@ static const struct pid_entry tid_base_stuff[] = {
 #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),
        ONE("statm",     S_IRUGO, pid_statm),
index bc0a0dd..cb4096c 100644 (file)
@@ -806,12 +806,9 @@ continue_removing:
        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 02eca2e..8bb03f0 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;
 
index 5acc001..f9a8b89 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 b31ab78..2aad104 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 2ec748b..879e54d 100644 (file)
@@ -521,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;
 
index d7c4935..bb3cb5b 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 3f13d49..8e51a2a 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 2294783..e4f8d51 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 376ef3e..3528f40 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 3994421..b30311b 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);
@@ -1161,36 +1161,6 @@ static long do_splice(struct file *in, loff_t __user *off_in,
 }
 
 /*
- * 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
  * our ones pages[] map instead of splitting that operation into pieces.
@@ -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 9cf41f7..7c46fbe 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 c1a7efb..aedaeba 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 3f07893..c9e4e50 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 eeba384..fe61194 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 c5d60de..df0d435 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 005a3b8..8565e58 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 00eb9c6..ca1e2d4 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 44cc702..5698bbf 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 227c9d7..3e30e40 100644 (file)
@@ -1302,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 b6b664e..6929e3e 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 4706a8b..468377e 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 5e95649..a20683c 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 a42ba9d..01939ba 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 2bf287e..5fc61c8 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 5e3b575..82333b3 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 742b2c7..9433812 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 bdca155..d8c3e3c 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 db351d1..a5801ae 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/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 d31fd49..2a14302 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-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 94de788..48bbd85 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 13ec7ed..a25d18f 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 b695253..21aa8ac 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 b699d0d..2e20131 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 8403059..1b80a48 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 b14cbda..193f6c1 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 5c60bfc..9a1db20 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 70b0fe7..e68a1cb 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 e99406a..f41335b 100644 (file)
@@ -56,7 +56,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 1b882a2..9cb0190 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/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 75feb15..2d84792 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 71211c8..d08a1f2 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 a378386..e60e907 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 57dc672..0399359 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/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 7603383..320aa5e 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 c0d5259..3cd4b52 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 7f34cd3..de28e6e 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 30303fc..67a03a8 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 ff95e9d..168f125 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
index 4725268..b7b166f 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 0612d0c..cfd8ad4 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 82134f5..f1a70db 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 008ca66..cbe03f4 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 cefcf8b..9bb87e9 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 f8f3190..995c06b 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 0612d0c..cfd8ad4 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 3f45590..abde24c 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 9ad979d..f67698f 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 5e94271..c41f9cf 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 cb8b0f1..bba82dc 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 cefcf8b..9bb87e9 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 439a589..e163260 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 3c7ce16..e3128df 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 1c00407..6f3995b 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 edc8d1b..cb2fb25 100644 (file)
@@ -120,7 +120,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/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 2e8966c..b289887 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;
 }
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 e2468f8..82cd0cb 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 783ab99..189486c 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 a3034d2..c764a8f 100644 (file)
@@ -13,7 +13,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
index 25c10e9..37b3706 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
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 729f6b0..6d88a92 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)                                              \
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 0721a5e..a6d50c7 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 */
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 a26cdeb..91f7944 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;
 }
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
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 230b3f1..c64afb4 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/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 7c882fc..ccae8f6 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;
 }
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 2f1e1b0..b7ca6dc 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 c6c0e9f..53af696 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
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 74c5497..c7ca45f 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 5a21115..a8b0687 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);
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 c9601df..6b18ba9 100644 (file)
@@ -46,6 +46,8 @@
 #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 | \
index 7e54adb..07b0d8f 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 */
index bdbab72..6fe39e3 100644 (file)
@@ -401,6 +401,9 @@ extern int icache_44x_need_flush;
 #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
index ba80003..5fc78c0 100644 (file)
@@ -245,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; }
@@ -265,7 +265,7 @@ 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;
index 3d6e310..734e075 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
index a8c7bab..a7360cd 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 416d4c2..4d28e1e 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 a9db562..9665a26 100644 (file)
@@ -108,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 */
@@ -125,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 100c6fb..c32da6f 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 3234dd5..3c55e41 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
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 b550a27..720dfab 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 5fd5c89..065306d 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 da46e67..c23af81 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 d8f9872..efd511d 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 22cc419..6c0b8a2 100644 (file)
@@ -171,7 +171,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 05092da..f01449a 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 7438d1e..d557b00 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 = {                                 \
index 2329363..10016e0 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 eb0358c..fdcb93b 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 87e812f..8589a50 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 5dc01d2..77fb8bf 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
index cbc731d..72ea209 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 b7c7ce8..15d9f92 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_SH_PROCESSOR_H
 
 #include <asm/cpu-features.h>
+#include <asm/segment.h>
 
 #ifndef __ASSEMBLY__
 /*
index c09305d..c6583f2 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 88a2edf..fc7fc68 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 7d36dc3..643ab5a 100644 (file)
@@ -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 bd2596c..eb23000 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 e7914a5..9845846 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 3690fe5..e971d9a 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 e417eab..5e2725f 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/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 */
+
index e65b6b8..056d68c 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 5131e39..eeb4c74 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
index 701ba84..327f7eb 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 b3440c3..45c2c9b 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 1e41fda..892fd6d 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 a9b68d0..81b3d51 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 4b21f36..65be656 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 0b07212..d52c000 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 9d21eab..7c54e91 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/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-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/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/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/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
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__ */
index 87a7153..3c034f4 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 c2ddd3d..0eaa9bf 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,
index 116e914..c4c91b3 100644 (file)
 #ifndef _ASM_I386_GPIO_H
 #define _ASM_I386_GPIO_H
 
-#ifdef CONFIG_X86_RDC321X
-#include <gpio.h>
-#else /* CONFIG_X86_RDC321X */
-
 #include <asm-generic/gpio.h>
 
 #ifdef CONFIG_GPIOLIB
@@ -57,6 +53,4 @@ static inline int irq_to_gpio(unsigned int irq)
 
 #endif /* CONFIG_GPIOLIB */
 
-#endif /* CONFIG_X86_RDC321X */
-
 #endif /* _ASM_I386_GPIO_H */
index d63166f..ecc8061 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 8f855a1..c0e52a1 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 fdde0be..bc34dc2 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 75d2c95..c47e2ab 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 3e5dbc4..04caa2f 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 c706a74..2730b35 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 f6fa4d8..5f702d1 100644 (file)
@@ -451,3 +451,4 @@ extern struct movsl_mask {
 #endif
 
 #endif
+
index 3c7d537..51882ae 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/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 b51ddd2..09b276c 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 31b7531..dcc228a 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 6cd39a9..025e4f5 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;
index 49d8eb7..8252b04 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
@@ -499,7 +502,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 +795,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 +824,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)
@@ -1136,7 +1139,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 *);
@@ -1272,7 +1275,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);
@@ -1696,9 +1699,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 *);
 
@@ -1767,7 +1770,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));
 
@@ -1831,7 +1834,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 *);
index 282f542..9e5a06e 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 9a71d4c..32e0ef0 100644 (file)
@@ -273,7 +273,10 @@ struct hstate {};
 #define huge_page_mask(h) PAGE_MASK
 #define huge_page_order(h) 0
 #define huge_page_shift(h) PAGE_SHIFT
-#define pages_per_huge_page(h) 1
+static inline unsigned int pages_per_huge_page(struct hstate *h)
+{
+       return 1;
+}
 #endif
 
 #endif /* _LINUX_HUGETLB_H */
index 7d51cbc..75ae6d8 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 42ae954..11b84e1 100644 (file)
@@ -170,6 +170,13 @@ extern void (*late_time_init)(void);
        __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.
  *
index 6b563ca..da720bc 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 3265968..82f88a8 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"
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 d31e36e..523a286 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 37a5cdb..a9f998a 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 e27082c..bf8f119 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:
index d87a5a5..6e695ea 100644 (file)
@@ -810,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);
@@ -833,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.
  *
index 0d508ac..ee6e822 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 10a2080..9c288c9 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;
 };
 
index 4374d1a..b5efaa2 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 9a6e2f9..310e616 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 b0ddf4b..d6fb115 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 25724f7..d802f77 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 ed8dc67..c02f3d2 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 9addd07..0a6d516 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 39e7d2a..08dd131 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 d996091..0be442f 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 256e734..df362dd 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 85fd041..64ee53c 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 9c1d954..aa30244 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 8b5d491..4ed40ca 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 53ea3dc..83f6787 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 12c5bc3..090da50 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 001eec5..dcaf611 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 7c37d7e..5014f7a 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 0dc07d5..c8e63a5 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 0e37ad0..e07890a 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 5cc070c..27ad40a 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 e9d40bd..36efcba 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 24d88e9..68f8c32 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 29d2619..78a5922 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 59a61bd..79886ad 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 ee1ec2c..a81d818 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
@@ -62,6 +63,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,7 +226,7 @@ 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);
@@ -141,6 +234,22 @@ 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.
  */
 static inline loff_t page_offset(struct page *page)
index dcb9e01..6a0d7cd 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 c3b1761..35a7841 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_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 4cdd393..fac3337 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 f560d17..fb61850 100644 (file)
@@ -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 c6f5f9d..fd31756 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 b8ce2b4..a916c66 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)
index 66a9681..af135ae 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 6cd8c44..953fc05 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 b01fe00..91f597a 100644 (file)
@@ -225,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 f4d386c..ca643b1 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 42036ff..5270d44 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,9 +505,6 @@ 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;
-#ifdef CONFIG_TASK_XACCT
-       u64 rchar, wchar, syscr, syscw;
-#endif
        struct task_io_accounting ioac;
 
        /*
@@ -1257,10 +1253,6 @@ 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 */
@@ -1797,7 +1789,7 @@ 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);
@@ -1883,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)
@@ -2139,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
@@ -2196,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)
@@ -2231,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 f0e9adb..fd96e7f 100644 (file)
@@ -1362,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);
@@ -1628,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);
@@ -2021,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 e72716c..25641d9 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 f2d12d5..fd83f25 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 4110391..5ff9676 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 *);
index d117ea2..5bad61a 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 48262f8..66484d4 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 950af63..dc5086f 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.  */
index a9cc29d..4be01bb 100644 (file)
@@ -778,8 +778,20 @@ 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 *);
 
 static inline void
index 4bf8cad..e530026 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 5bfc553..f1cb0ba 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 e8e6915..c634350 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 0b33776..de40f16 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 24141b4..d0437f3 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 44d00e9..5e88afc 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 ff46c6f..4d090f9 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 */
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> */
index 9385a56..15a653d 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 2e66a95..e466bd5 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 018f920..3e68c8d 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 db8823d..e69de29 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 89c442e..1d10409 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 5660ea2..a8ad75a 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 2a52774..41b509b 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 020d057..07d3a9a 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 33f379b..2745e1a 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 9b1e252..e17eda3 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 d508ef0..001685d 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 615072c..c6c61cd 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 713f34d..170ceca 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 b2bca18..390d21c 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 2dfa96b..7dd29b7 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 b5862b9..250e6ef 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 2d5c185..113028f 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 3855620..a8eb43c 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 0c96e7b..8d6e991 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 3140cc5..4f0d8c1 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 90b529f..936e333 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 00137a7..5c40cc5 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 66c9448..f9f6e79 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 6467f78..291d56a 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 3ad2303..33efce2 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 2a9add2..06a8790 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 a594bac..44a55d1 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 1ccf462..613173b 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)
index a50bdfe..43d6989 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.
 
index f769fac..3715feb 100644 (file)
@@ -23,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 735705d..9aa968d 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 0604cbc..20fdc98 100644 (file)
@@ -743,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 */
@@ -774,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 1fdc2eb..96fb36c 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;
 
@@ -638,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 66ec9fd..657f8f8 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>
 
@@ -1529,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);
index 10ba5f1..29510d6 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,8 +275,6 @@ 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:
index c1ef192..0d407e8 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 ad933bb..eb4d647 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>
@@ -120,18 +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);
-#ifdef CONFIG_TASK_XACCT
-               sig->rchar += tsk->rchar;
-               sig->wchar += tsk->wchar;
-               sig->syscr += tsk->syscr;
-               sig->syscw += tsk->syscw;
-#endif /* CONFIG_TASK_XACCT */
-#ifdef CONFIG_TASK_IO_ACCOUNTING
-               sig->ioac.read_bytes += tsk->ioac.read_bytes;
-               sig->ioac.write_bytes += tsk->ioac.write_bytes;
-               sig->ioac.cancelled_write_bytes +=
-                                       tsk->ioac.cancelled_write_bytes;
-#endif /* CONFIG_TASK_IO_ACCOUNTING */
+               task_io_accounting_add(&sig->ioac, &tsk->ioac);
                sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
                sig = NULL; /* Marker for below. */
        }
@@ -162,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);
 
        /*
@@ -204,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);
@@ -567,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);
        }
 }
@@ -887,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:
@@ -924,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) &&
@@ -949,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);
 }
 
@@ -1029,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
@@ -1378,21 +1352,8 @@ static int wait_task_zombie(struct task_struct *p, int options,
                psig->coublock +=
                        task_io_get_oublock(p) +
                        sig->oublock + sig->coublock;
-#ifdef CONFIG_TASK_XACCT
-               psig->rchar += p->rchar + sig->rchar;
-               psig->wchar += p->wchar + sig->wchar;
-               psig->syscr += p->syscr + sig->syscr;
-               psig->syscw += p->syscw + sig->syscw;
-#endif /* CONFIG_TASK_XACCT */
-#ifdef CONFIG_TASK_IO_ACCOUNTING
-               psig->ioac.read_bytes +=
-                       p->ioac.read_bytes + sig->ioac.read_bytes;
-               psig->ioac.write_bytes +=
-                       p->ioac.write_bytes + sig->ioac.write_bytes;
-               psig->ioac.cancelled_write_bytes +=
-                               p->ioac.cancelled_write_bytes +
-                               sig->ioac.cancelled_write_bytes;
-#endif /* CONFIG_TASK_IO_ACCOUNTING */
+               task_io_accounting_add(&psig->ioac, &p->ioac);
+               task_io_accounting_add(&psig->ioac, &sig->ioac);
                spin_unlock_irq(&p->parent->sighand->siglock);
        }
 
index b99d73e..8214ba7 100644 (file)
@@ -37,6 +37,7 @@
 #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>
@@ -656,13 +657,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;
@@ -812,12 +806,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;
-#ifdef CONFIG_TASK_XACCT
-       sig->rchar = sig->wchar = sig->syscr = sig->syscw = 0;
-#endif
-#ifdef CONFIG_TASK_IO_ACCOUNTING
-       memset(&sig->ioac, 0, sizeof(sig->ioac));
-#endif
+       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]);
@@ -865,8 +854,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);
 }
@@ -907,7 +895,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;
@@ -1000,13 +989,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;
@@ -1163,8 +1146,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
@@ -1195,7 +1176,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);
 
@@ -1237,8 +1217,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)
@@ -1323,29 +1302,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.
  *
@@ -1380,14 +1343,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.
@@ -1405,32 +1368,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);
@@ -1442,7 +1408,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 964964b..3cd441e 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 f8914b9..152abfd 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;
index 1c5fcac..c8a4370 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 6111c27..96cff2f 100644 (file)
@@ -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;
index d8b5605..61d2121 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 95bff23..0b7476f 100644 (file)
@@ -635,6 +635,13 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t 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)
index 700f44e..acc0c10 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 8392a9d..082b3fc 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 6f8696c..aad93cd 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 7de644c..04006ef 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 0047bd9..0236958 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,9 +1921,21 @@ 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;
 }
 
 /***
@@ -6389,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;
@@ -6399,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 82c3545..954f77d 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);
 }
 
 
@@ -591,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
@@ -756,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.
                 */
@@ -1323,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;
@@ -1396,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)
@@ -1599,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);
@@ -1735,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);
@@ -1748,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) {
@@ -1806,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;
                        }
@@ -1827,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
@@ -1836,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);
@@ -1884,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);
@@ -1895,7 +1923,6 @@ EXPORT_SYMBOL(recalc_sigpending);
 EXPORT_SYMBOL_GPL(dequeue_signal);
 EXPORT_SYMBOL(flush_signals);
 EXPORT_SYMBOL(force_sig);
-EXPORT_SYMBOL(ptrace_notify);
 EXPORT_SYMBOL(send_sig);
 EXPORT_SYMBOL(send_sig_info);
 EXPORT_SYMBOL(sigprocmask);
@@ -2299,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 462c785..96fc7c0 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 f6b03d5..c506f26 100644 (file)
@@ -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 7bd8d1a..b75b492 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 738b411..e446c7c 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 0c9d3fa..c018580 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:
index 35a50db..fe47133 100644 (file)
@@ -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[];
@@ -1386,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
@@ -1394,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)
@@ -1403,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,
@@ -1480,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;
 
@@ -1524,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--;
@@ -1599,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;
 }
@@ -1609,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;
 
@@ -1644,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
@@ -1720,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)
@@ -1765,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);
@@ -1772,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;
@@ -1828,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);
-       kfree(header);
+}
+
+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);
+       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 */
@@ -1848,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 4231a3d..f6e3af3 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 868e121..8f3fb3d 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 421d6fe..ece6cfb 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 3c8d61d..e303ccb 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 3da47cc..8ebcd85 100644 (file)
@@ -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;
index 9085ad6..3b1f94b 100644 (file)
@@ -11,7 +11,7 @@ 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
@@ -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
 
index f861963..45a6bde 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++;
 }
@@ -733,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 3476f82..e728c7f 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -607,7 +607,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id)
 }
 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));
 }
index 37a3ea4..d322293 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 9f8d599..3f91472 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 3074a02..d6c64a8 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 56ec21a..be86b32 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;
@@ -905,6 +976,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));
 }
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 d568894..977edbd 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 aa79900..efee5d3 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
index 8433645..4297bc4 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 2d3ec1f..5de7633 100644 (file)
 /*
  * 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)
 {
@@ -141,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)
@@ -442,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
+               } 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_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)
@@ -633,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);
@@ -656,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);
@@ -747,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;
 }
 
@@ -774,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);
 
@@ -806,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);
@@ -1665,8 +1758,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;
@@ -1680,7 +1774,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)
@@ -2436,7 +2530,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;
 
index 3e744ab..98a3f31 100644 (file)
@@ -380,7 +380,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 a8bf4ab..3be79dc 100644 (file)
@@ -1026,18 +1026,6 @@ static void __init report_hugepages(void)
        }
 }
 
-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
 #ifdef CONFIG_HIGHMEM
 static void try_to_free_low(struct hstate *h, unsigned long count)
 {
@@ -1386,6 +1374,18 @@ static int __init hugetlb_default_setup(char *s)
 }
 __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)
index 262e3eb..a8ca04f 100644 (file)
@@ -374,7 +374,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",
index d8c65a6..153572f 100644 (file)
@@ -285,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);
@@ -305,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) {
@@ -314,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;
        }
 
@@ -338,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.
@@ -357,10 +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);
-       if (!PageSwapCache(newpage)) {
+       spin_unlock_irq(&mapping->tree_lock);
+       if (!PageSwapCache(newpage))
                mem_cgroup_uncharge_cache_page(page);
-       }
 
        return 0;
 }
index 4462b6a..5edccd9 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 94c6d89..24de8b6 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 6da6672..3cf3d05 100644 (file)
@@ -2372,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;
@@ -2397,7 +2397,7 @@ void build_all_zonelists(void)
        } 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();
index d8723a5..77e8ddf 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 abbd29f..39ae5a9 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -138,7 +138,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;
 
index f92fea9..952d361 100644 (file)
@@ -936,7 +936,7 @@ found:
        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,
+               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 */
@@ -1301,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);
@@ -2352,7 +2352,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;
 
index f5664c5..8e5aadd 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 052e7d6..918f04f 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 de268eb..d8fbd4d 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -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 77c21cf..b7e2cd5 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1012,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.
@@ -1040,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;
 }
@@ -1103,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)
@@ -2286,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;
@@ -3042,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;
 
@@ -3082,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;
 
index 8ffc089..5d9dbbb 100644 (file)
@@ -377,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 d8aadaf..b8035b0 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 2f33edb..6beb625 100644 (file)
@@ -33,8 +33,8 @@
 #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;
@@ -44,7 +44,7 @@ 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];
 
@@ -369,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);
 
index b8961cb..e68443d 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 8f18683..9341ca7 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 35f2938..85b9a0d 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;
        }
 
index 26672c6..8f71761 100644 (file)
@@ -391,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.
         *
@@ -427,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;
 }
 
@@ -598,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:
@@ -623,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;
 }
index 07b5b82..0c85042 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 690bc3a..1a58af5 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 5b495fe..f60c1e7 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 8a28fc9..dd61dca 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 53af784..8d13a9b 100644 (file)
@@ -1973,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);
                }
        }
@@ -3847,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);
@@ -4169,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 2d3035d..7552495 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 e411567..4e0c922 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 4a0ad15..a6b3437 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 8c6b706..164b090 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 32617e0..1c2e3ec 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 08392ed..df2f110 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 2622ace..882c5c4 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 b74e8b2..5e1ee0d 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 fe20068..d06945c 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 a0b5600..b622d97 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 3608d53..54b3c7e 100644 (file)
@@ -99,21 +99,11 @@ static void dccp_retransmit_timer(struct sock *sk)
        }
 
        /*
-        * 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 f440a9f..8a3ac1f 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);
@@ -338,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);
@@ -658,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);
 
@@ -1439,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 2e667e2..91d3d96 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 bb81c95..0c1ae68 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 0546a0b..6c52e08 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 115f537..4498190 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 75c2def..d985bd6 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 38d38f0..2152d22 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 465544f..d533a89 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 a42b64d..38ccb6d 100644 (file)
@@ -104,9 +104,7 @@ out:
 
 static int ipcomp4_init_state(struct xfrm_state *x)
 {
-       int err;
-       struct ipcomp_data *ipcd;
-       struct xfrm_algo_desc *calg_desc;
+       int err = -EINVAL;
 
        x->props.header_len = 0;
        switch (x->props.mode) {
index 3be4d07..082f5dd 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 2b472ac..db6d312 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 e4ab0ac..380d647 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 51bc24d..9d38005 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 14ef202..770d827 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 0b491bf..1ab341e 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 75efd24..67ccce2 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) {
@@ -3877,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 a82df63..a2b06d0 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 328e0cf..5ab6ba1 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 74d543d..a7842c5 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 60461ad..95055f8 100644 (file)
@@ -150,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);
@@ -934,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
@@ -1058,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);
@@ -1113,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 87801cc..16d43f2 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 00a8a5f..1646a56 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 08ea2de..52dddc2 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 6407c64..6811901 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 0cfcea4..4545e43 100644 (file)
@@ -134,9 +134,7 @@ out:
 
 static int ipcomp6_init_state(struct xfrm_state *x)
 {
-       int err;
-       struct ipcomp_data *ipcd;
-       struct xfrm_algo_desc *calg_desc;
+       int err = -EINVAL;
 
        x->props.header_len = 0;
        switch (x->props.mode) {
index ad1cc5b..31295c8 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 a07abee..6e71310 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 cf20bc4..52d06dd 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 6ab957e..89184b5 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 6a68eeb..a46badd 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 5c99274..e6dfaea 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 ae45f98..cff778b 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 f0fc46c..d628df9 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 3469bc7..4b2c769 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 98bfe27..b0eacc0 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 d56cae1..c718e7e 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 4b2682f..32e4891 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 74e662c..d308c19 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 32c3f9d..38015b4 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 527db25..246f906 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 04faa83..6b517b9 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 f1d2f8e..14954bf 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 43abd4d..fd2a6ca 100644 (file)
@@ -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 30c999c..75a4095 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 73f5384..8589da6 100644 (file)
@@ -536,14 +536,7 @@ static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
 
        opt.limit = q->limit;
        opt.divisor = SFQ_HASH_DIVISOR;
-       opt.flows = 0;
-       if (q->tail != SFQ_DEPTH) {
-               unsigned int i;
-
-               for (i = 0; i < SFQ_HASH_DIVISOR; i++)
-                       if (q->ht[i] != SFQ_DEPTH)
-                               opt.flows++;
-       }
+       opt.flows = q->limit;
 
        NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
 
index ec2a0a3..8472b8b 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 1310a82..8ef8ba8 100644 (file)
@@ -265,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;
 
index 5a9b0e7..23a2b8f 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 a19b22b..84d3283 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 63ada43..972201c 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 int is_seen(struct ctl_table_set *set)
+{
+       return &current->nsproxy->net_ns->sysctls == set;
 }
 
 /* Return standard mode bits for table entry. */
@@ -53,13 +58,6 @@ static struct ctl_table_root net_sysctl_root = {
        .permissions = net_ctl_permissions,
 };
 
-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 &net_sysctl_ro_tables;
-}
-
 static int net_ctl_ro_header_perms(struct ctl_table_root *root,
                struct nsproxy *namespaces, struct ctl_table *table)
 {
@@ -70,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;
 }
 
@@ -98,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 70ceb16..015606b 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 ebdff3d..2a27b84 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 23a2cc0..96036cf 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) {
index 800f669..c609a4b 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/percpu.h>
-#include <linux/rtnetlink.h>
 #include <linux/smp.h>
 #include <linux/vmalloc.h>
 #include <net/ip.h>
@@ -251,7 +250,7 @@ static void ipcomp_free_tfms(struct crypto_comp **tfms)
                        break;
        }
 
-       BUG_TRAP(pos);
+       WARN_ON(!pos);
 
        if (--pos->users)
                return;
index 72fddaf..4c6914e 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 53dae3e..612dc13 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: ;
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()
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 fda6313..9fba838 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 ee5fe94..0759761 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 96521cb..4a9af6f 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 88e3934..d8f77e2 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 1c1bdaf..83b7512 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 5b01c0b..63d10da 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 59f23b5..ff70687 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 63f131f..40d06c5 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 ee5a51c..1b40e55 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 87e3aef..83e9005 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 dbe63db..4d4b8dd 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 41c047e..0797ca4 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 07364c0..8c49a00 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 0746e9c..f4fbc79 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 7e3e894..974e051 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 fbf1124..9bf9536 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 16715a6..ef9f072 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 2807bc8..add4e87 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 08cb77f..7fdafcb 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 ba4b5c1..9384702 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 9fc8edd..1fb7f9a 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 2c87061..820347c 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;
                        }
                }
        }