]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'upstream-davem' of master.kernel.org:/pub/scm/linux/kernel/git/linville...
authorDavid S. Miller <davem@sunset.davemloft.net>
Sun, 15 Jul 2007 01:58:49 +0000 (18:58 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Sun, 15 Jul 2007 01:58:49 +0000 (18:58 -0700)
1054 files changed:
Documentation/ABI/testing/sysfs-bus-usb
Documentation/DMA-mapping.txt
Documentation/DocBook/kernel-api.tmpl
Documentation/blackfin/kgdb.txt [new file with mode: 0644]
Documentation/feature-removal-schedule.txt
Documentation/firmware_class/firmware_sample_firmware_class.c
Documentation/i2c/busses/i2c-i801
Documentation/i2c/busses/i2c-piix4
Documentation/i2c/busses/i2c-taos-evm [new file with mode: 0644]
Documentation/i2c/chips/max6875
Documentation/i2c/chips/x1205 [deleted file]
Documentation/i2c/summary
Documentation/i2c/writing-clients
Documentation/i386/zero-page.txt
Documentation/ia64/aliasing-test.c
Documentation/ia64/aliasing.txt
Documentation/networking/ip-sysctl.txt
Documentation/pci.txt
Documentation/power/pci.txt
Documentation/power/swsusp.txt
Documentation/sysctl/vm.txt
Documentation/sysfs-rules.txt [new file with mode: 0644]
Documentation/usb/dma.txt
Documentation/usb/persist.txt [new file with mode: 0644]
MAINTAINERS
arch/alpha/Kconfig
arch/alpha/kernel/pci_iommu.c
arch/arm/Kconfig
arch/arm/boot/compressed/.gitignore
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head-xscale.S
arch/arm/boot/compressed/head.S
arch/arm/common/locomo.c
arch/arm/common/sa1111.c
arch/arm/common/sharpsl_pm.c
arch/arm/kernel/head-common.S
arch/arm/kernel/head.S
arch/arm/kernel/process.c
arch/arm/kernel/setup.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-davinci/Makefile
arch/arm/mach-davinci/board-evm.c
arch/arm/mach-davinci/clock.c [new file with mode: 0644]
arch/arm/mach-davinci/clock.h [new file with mode: 0644]
arch/arm/mach-davinci/gpio.c [new file with mode: 0644]
arch/arm/mach-davinci/io.c
arch/arm/mach-davinci/mux.c [new file with mode: 0644]
arch/arm/mach-davinci/psc.c
arch/arm/mach-imx/generic.c
arch/arm/mach-imx/time.c
arch/arm/mach-iop13xx/setup.c
arch/arm/mach-iop13xx/tpmi.c
arch/arm/mach-iop32x/glantank.c
arch/arm/mach-iop32x/iq31244.c
arch/arm/mach-iop32x/iq80321.c
arch/arm/mach-iop32x/n2100.c
arch/arm/mach-iop33x/iq80331.c
arch/arm/mach-iop33x/iq80332.c
arch/arm/mach-ixp4xx/Kconfig
arch/arm/mach-ixp4xx/Makefile
arch/arm/mach-ixp4xx/gateway7001-pci.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/gateway7001-setup.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/gtwx5715-pci.c
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-ixp4xx/wg302v2-pci.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/wg302v2-setup.c [new file with mode: 0644]
arch/arm/mach-ks8695/Makefile
arch/arm/mach-ks8695/gpio.c [new file with mode: 0644]
arch/arm/mach-pxa/clock.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/devices.h [new file with mode: 0644]
arch/arm/mach-pxa/dma.c
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/generic.h
arch/arm/mach-pxa/idp.c
arch/arm/mach-pxa/irq.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/pm.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/time.c
arch/arm/mach-pxa/tosa.c
arch/arm/mach-pxa/trizeps4.c
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2440/mach-anubis.c
arch/arm/mach-s3c2440/mach-osiris.c
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-sa1100/pm.c
arch/arm/mach-sa1100/time.c
arch/arm/mm/ioremap.c
arch/arm/plat-iop/Makefile
arch/arm/plat-iop/adma.c [new file with mode: 0644]
arch/blackfin/Kconfig
arch/blackfin/Makefile
arch/blackfin/boot/Makefile
arch/blackfin/configs/BF548-EZKIT_defconfig [new file with mode: 0644]
arch/blackfin/kernel/Makefile
arch/blackfin/kernel/asm-offsets.c
arch/blackfin/kernel/bfin_dma_5xx.c
arch/blackfin/kernel/bfin_gpio.c
arch/blackfin/kernel/bfin_ksyms.c
arch/blackfin/kernel/cacheinit.c [new file with mode: 0644]
arch/blackfin/kernel/cplbinit.c [new file with mode: 0644]
arch/blackfin/kernel/dma-mapping.c
arch/blackfin/kernel/dualcore_test.c
arch/blackfin/kernel/fixed_code.S [new file with mode: 0644]
arch/blackfin/kernel/flat.c
arch/blackfin/kernel/irqchip.c
arch/blackfin/kernel/kgdb.c [new file with mode: 0644]
arch/blackfin/kernel/module.c
arch/blackfin/kernel/process.c
arch/blackfin/kernel/ptrace.c
arch/blackfin/kernel/setup.c
arch/blackfin/kernel/signal.c
arch/blackfin/kernel/sys_bfin.c
arch/blackfin/kernel/time.c
arch/blackfin/kernel/traps.c
arch/blackfin/kernel/vmlinux.lds.S
arch/blackfin/lib/strcmp.c
arch/blackfin/lib/strcpy.c
arch/blackfin/lib/strncmp.c
arch/blackfin/lib/strncpy.c
arch/blackfin/mach-bf533/Makefile
arch/blackfin/mach-bf533/boards/cm_bf533.c
arch/blackfin/mach-bf533/boards/ezkit.c
arch/blackfin/mach-bf533/boards/generic_board.c
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf533/cpu.c
arch/blackfin/mach-bf533/dma.c [new file with mode: 0644]
arch/blackfin/mach-bf533/head.S
arch/blackfin/mach-bf533/ints-priority.c
arch/blackfin/mach-bf537/Makefile
arch/blackfin/mach-bf537/boards/cm_bf537.c
arch/blackfin/mach-bf537/boards/eth_mac.c
arch/blackfin/mach-bf537/boards/generic_board.c
arch/blackfin/mach-bf537/boards/pnav10.c
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/dma.c [new file with mode: 0644]
arch/blackfin/mach-bf537/head.S
arch/blackfin/mach-bf537/ints-priority.c
arch/blackfin/mach-bf548/Kconfig [new file with mode: 0644]
arch/blackfin/mach-bf548/Makefile [new file with mode: 0644]
arch/blackfin/mach-bf548/boards/Makefile [new file with mode: 0644]
arch/blackfin/mach-bf548/boards/ezkit.c [new file with mode: 0644]
arch/blackfin/mach-bf548/boards/led.S [new file with mode: 0644]
arch/blackfin/mach-bf548/cpu.c [new file with mode: 0644]
arch/blackfin/mach-bf548/dma.c [new file with mode: 0644]
arch/blackfin/mach-bf548/gpio.c [new file with mode: 0644]
arch/blackfin/mach-bf548/head.S [new file with mode: 0644]
arch/blackfin/mach-bf548/ints-priority.c [new file with mode: 0644]
arch/blackfin/mach-bf561/Makefile
arch/blackfin/mach-bf561/boards/cm_bf561.c
arch/blackfin/mach-bf561/boards/ezkit.c
arch/blackfin/mach-bf561/boards/generic_board.c
arch/blackfin/mach-bf561/boards/tepla.c
arch/blackfin/mach-bf561/coreb.c
arch/blackfin/mach-bf561/dma.c [new file with mode: 0644]
arch/blackfin/mach-bf561/head.S
arch/blackfin/mach-bf561/ints-priority.c
arch/blackfin/mach-common/Makefile
arch/blackfin/mach-common/cacheinit.S
arch/blackfin/mach-common/cplbinfo.c
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/interrupt.S
arch/blackfin/mach-common/ints-priority-dc.c
arch/blackfin/mach-common/ints-priority-sc.c
arch/blackfin/mach-common/pm.c
arch/blackfin/mm/blackfin_sram.c
arch/blackfin/mm/init.c
arch/blackfin/oprofile/common.c
arch/blackfin/oprofile/op_model_bf533.c
arch/blackfin/oprofile/timer_int.c
arch/i386/Kconfig.cpu
arch/i386/boot/Makefile
arch/i386/boot/a20.c [new file with mode: 0644]
arch/i386/boot/apm.c [new file with mode: 0644]
arch/i386/boot/bitops.h [new file with mode: 0644]
arch/i386/boot/boot.h [new file with mode: 0644]
arch/i386/boot/bootsect.S [deleted file]
arch/i386/boot/cmdline.c [new file with mode: 0644]
arch/i386/boot/code16gcc.h [new file with mode: 0644]
arch/i386/boot/compressed/Makefile
arch/i386/boot/compressed/head.S
arch/i386/boot/copy.S [new file with mode: 0644]
arch/i386/boot/cpu.c [new file with mode: 0644]
arch/i386/boot/cpucheck.c [new file with mode: 0644]
arch/i386/boot/edd.S [deleted file]
arch/i386/boot/edd.c [new file with mode: 0644]
arch/i386/boot/header.S [new file with mode: 0644]
arch/i386/boot/main.c [new file with mode: 0644]
arch/i386/boot/mca.c [new file with mode: 0644]
arch/i386/boot/memory.c [new file with mode: 0644]
arch/i386/boot/pm.c [new file with mode: 0644]
arch/i386/boot/pmjump.S [new file with mode: 0644]
arch/i386/boot/printf.c [new file with mode: 0644]
arch/i386/boot/setup.S [deleted file]
arch/i386/boot/setup.ld [new file with mode: 0644]
arch/i386/boot/string.c [new file with mode: 0644]
arch/i386/boot/tools/build.c
arch/i386/boot/tty.c [new file with mode: 0644]
arch/i386/boot/version.c [new file with mode: 0644]
arch/i386/boot/vesa.h [new file with mode: 0644]
arch/i386/boot/video-bios.c [new file with mode: 0644]
arch/i386/boot/video-vesa.c [new file with mode: 0644]
arch/i386/boot/video-vga.c [new file with mode: 0644]
arch/i386/boot/video.S [deleted file]
arch/i386/boot/video.c [new file with mode: 0644]
arch/i386/boot/video.h [new file with mode: 0644]
arch/i386/boot/voyager.c [new file with mode: 0644]
arch/i386/kernel/cpu/Makefile
arch/i386/kernel/cpu/addon_cpuid_features.c [new file with mode: 0644]
arch/i386/kernel/cpu/common.c
arch/i386/kernel/cpu/cpufreq/Kconfig
arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/kernel/cpu/cpufreq/longhaul.h
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
arch/i386/kernel/cpu/proc.c
arch/i386/kernel/e820.c
arch/i386/kernel/setup.c
arch/i386/kernel/verify_cpu.S [deleted file]
arch/i386/mach-visws/traps.c
arch/i386/pci/fixup.c
arch/ia64/Kconfig
arch/ia64/kernel/gate.S
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca_asm.S
arch/ia64/kernel/mca_drv_asm.S
arch/ia64/kernel/process.c
arch/ia64/mm/tlb.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/io_acpi_init.c
arch/ia64/sn/kernel/io_init.c
arch/ia64/sn/kernel/tiocx.c
arch/ia64/sn/pci/pcibr/pcibr_provider.c
arch/mips/Kconfig
arch/mips/au1000/common/setup.c
arch/mips/au1000/common/time.c
arch/mips/au1000/pb1200/board_setup.c
arch/mips/configs/jazz_defconfig
arch/mips/configs/qemu_defconfig
arch/mips/configs/rm200_defconfig
arch/mips/configs/yosemite_defconfig
arch/mips/kernel/Makefile
arch/mips/kernel/branch.c
arch/mips/kernel/entry.S
arch/mips/kernel/genex.S
arch/mips/kernel/pcspeaker.c [moved from arch/mips/kernel/i8253.c with 100% similarity]
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/traps.c
arch/mips/lib/dump_tlb.c
arch/mips/lib/r3k_dump_tlb.c
arch/mips/lib/uncached.c
arch/mips/math-emu/cp1emu.c
arch/mips/math-emu/dsemul.c
arch/mips/mipssim/sim_int.c
arch/mips/mipssim/sim_setup.c
arch/mips/mipssim/sim_time.c
arch/mips/pci/Makefile
arch/mips/pci/fixup-cobalt.c
arch/mips/pci/pci-dac.c [deleted file]
arch/mips/pci/pci.c
arch/mips/sibyte/swarm/time.c [deleted file]
arch/mips/sni/a20r.c
arch/mips/sni/rm200.c
arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
arch/mips/vr41xx/common/Makefile
arch/mips/vr41xx/common/giu.c [new file with mode: 0644]
arch/mips/vr41xx/common/rtc.c [new file with mode: 0644]
arch/mips/vr41xx/common/siu.c [new file with mode: 0644]
arch/powerpc/Kconfig
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
arch/ppc/Kconfig
arch/ppc/kernel/pci.c
arch/ppc/syslib/mv64x60.c
arch/s390/kernel/ipl.c
arch/sparc/Kconfig
arch/sparc64/Kconfig
arch/sparc64/kernel/pci.c
arch/x86_64/Kconfig
arch/x86_64/boot/Makefile
arch/x86_64/boot/bootsect.S [deleted file]
arch/x86_64/boot/compressed/Makefile
arch/x86_64/boot/compressed/head.S
arch/x86_64/boot/install.sh [deleted file]
arch/x86_64/boot/mtools.conf.in [deleted file]
arch/x86_64/boot/setup.S [deleted file]
arch/x86_64/boot/tools/build.c [deleted file]
arch/x86_64/kernel/Makefile
arch/x86_64/kernel/cpufreq/Kconfig
arch/x86_64/kernel/pci-dma.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/verify_cpu.S
crypto/Kconfig
crypto/Makefile
crypto/async_tx/Kconfig [new file with mode: 0644]
crypto/async_tx/Makefile [new file with mode: 0644]
crypto/async_tx/async_memcpy.c [new file with mode: 0644]
crypto/async_tx/async_memset.c [new file with mode: 0644]
crypto/async_tx/async_tx.c [new file with mode: 0644]
crypto/async_tx/async_xor.c [new file with mode: 0644]
crypto/xor.c [moved from drivers/md/xor.c with 69% similarity]
drivers/acpi/processor_core.c
drivers/ata/Kconfig
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-sff.c
drivers/ata/pata_ali.c
drivers/ata/pata_amd.c
drivers/ata/pata_cs5530.c
drivers/ata/pata_hpt3x3.c
drivers/ata/pata_it821x.c
drivers/ata/pata_mpc52xx.c
drivers/ata/pata_scc.c
drivers/ata/pata_serverworks.c
drivers/ata/pata_sis.c
drivers/ata/pata_sl82c105.c
drivers/ata/pata_via.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_promise.c
drivers/ata/sata_sis.c
drivers/ata/sata_uli.c
drivers/ata/sata_via.c
drivers/atm/eni.c
drivers/atm/idt77252.c
drivers/atm/iphase.c
drivers/atm/lanai.c
drivers/atm/zatm.c
drivers/base/attribute_container.c
drivers/base/base.h
drivers/base/bus.c
drivers/base/class.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/devres.c
drivers/base/firmware_class.c
drivers/base/power/main.c
drivers/base/power/power.h
drivers/base/power/resume.c
drivers/base/power/runtime.c
drivers/base/power/suspend.c
drivers/base/sys.c
drivers/block/pktcdvd.c
drivers/block/ub.c
drivers/char/Kconfig
drivers/char/agp/amd-k7-agp.c
drivers/char/agp/amd64-agp.c
drivers/char/agp/backend.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/vr41xx_giu.c
drivers/clocksource/acpi_pm.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/cpufreq_userspace.c
drivers/cpufreq/freq_table.c
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/dmaengine.c
drivers/dma/ioatdma.c
drivers/dma/ioatdma.h
drivers/dma/ioatdma_io.h [deleted file]
drivers/dma/iop-adma.c [new file with mode: 0644]
drivers/firmware/Kconfig
drivers/firmware/Makefile
drivers/firmware/dcdbas.c
drivers/firmware/dcdbas.h
drivers/firmware/dell_rbu.c
drivers/firmware/dmi-id.c [new file with mode: 0644]
drivers/firmware/dmi_scan.c
drivers/firmware/edd.c
drivers/firmware/efivars.c
drivers/hid/usbhid/hid-core.c
drivers/i2c/algos/Kconfig
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-iop3xx.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-pmcmsp.c [new file with mode: 0644]
drivers/i2c/busses/i2c-powermac.c
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/i2c-rpx.c [deleted file]
drivers/i2c/busses/i2c-savage4.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-taos-evm.c [new file with mode: 0644]
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/chips/Kconfig
drivers/i2c/chips/Makefile
drivers/i2c/chips/ds1682.c [new file with mode: 0644]
drivers/i2c/chips/eeprom.c
drivers/i2c/chips/max6875.c
drivers/i2c/chips/tsl2550.c [new file with mode: 0644]
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/ide/legacy/hd.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/amd74xx.c
drivers/ide/pci/cmd64x.c
drivers/ide/pci/cs5530.c
drivers/ide/pci/hpt366.c
drivers/ide/pci/piix.c
drivers/ide/pci/serverworks.c
drivers/ide/pci/sis5513.c
drivers/ide/pci/sl82c105.c
drivers/ide/pci/via82cxxx.c
drivers/infiniband/Kconfig
drivers/infiniband/core/agent.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cm_msgs.h
drivers/infiniband/core/cma.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/multicast.c
drivers/infiniband/core/sa.h
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/smi.c
drivers/infiniband/core/smi.h
drivers/infiniband/core/sysfs.c
drivers/infiniband/core/ucm.c
drivers/infiniband/core/umem.c
drivers/infiniband/hw/amso1100/Kconfig
drivers/infiniband/hw/cxgb3/Kconfig
drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb3/cxio_wr.h
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb3/iwch_cm.h
drivers/infiniband/hw/cxgb3/iwch_provider.c
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/infiniband/hw/ehca/Kconfig
drivers/infiniband/hw/ehca/ehca_av.c
drivers/infiniband/hw/ehca/ehca_classes.h
drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
drivers/infiniband/hw/ehca/ehca_cq.c
drivers/infiniband/hw/ehca/ehca_hca.c
drivers/infiniband/hw/ehca/ehca_irq.c
drivers/infiniband/hw/ehca/ehca_irq.h
drivers/infiniband/hw/ehca/ehca_iverbs.h
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/ehca/ehca_qp.c
drivers/infiniband/hw/ehca/ehca_reqs.c
drivers/infiniband/hw/ehca/ehca_tools.h
drivers/infiniband/hw/ehca/ehca_uverbs.c
drivers/infiniband/hw/ehca/hcp_if.c
drivers/infiniband/hw/ehca/hcp_if.h
drivers/infiniband/hw/ehca/hipz_hw.h
drivers/infiniband/hw/ehca/ipz_pt_fn.h
drivers/infiniband/hw/ipath/Kconfig
drivers/infiniband/hw/ipath/ipath_common.h
drivers/infiniband/hw/ipath/ipath_cq.c
drivers/infiniband/hw/ipath/ipath_debug.h
drivers/infiniband/hw/ipath/ipath_diag.c
drivers/infiniband/hw/ipath/ipath_driver.c
drivers/infiniband/hw/ipath/ipath_eeprom.c
drivers/infiniband/hw/ipath/ipath_file_ops.c
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/hw/ipath/ipath_iba6110.c
drivers/infiniband/hw/ipath/ipath_iba6120.c
drivers/infiniband/hw/ipath/ipath_init_chip.c
drivers/infiniband/hw/ipath/ipath_intr.c
drivers/infiniband/hw/ipath/ipath_kernel.h
drivers/infiniband/hw/ipath/ipath_keys.c
drivers/infiniband/hw/ipath/ipath_layer.c
drivers/infiniband/hw/ipath/ipath_layer.h
drivers/infiniband/hw/ipath/ipath_mad.c
drivers/infiniband/hw/ipath/ipath_mmap.c
drivers/infiniband/hw/ipath/ipath_mr.c
drivers/infiniband/hw/ipath/ipath_qp.c
drivers/infiniband/hw/ipath/ipath_rc.c
drivers/infiniband/hw/ipath/ipath_registers.h
drivers/infiniband/hw/ipath/ipath_ruc.c
drivers/infiniband/hw/ipath/ipath_srq.c
drivers/infiniband/hw/ipath/ipath_stats.c
drivers/infiniband/hw/ipath/ipath_sysfs.c
drivers/infiniband/hw/ipath/ipath_uc.c
drivers/infiniband/hw/ipath/ipath_ud.c
drivers/infiniband/hw/ipath/ipath_user_pages.c
drivers/infiniband/hw/ipath/ipath_verbs.c
drivers/infiniband/hw/ipath/ipath_verbs.h
drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
drivers/infiniband/hw/ipath/ipath_wc_ppc64.c
drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
drivers/infiniband/hw/mlx4/Kconfig
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/mlx4_ib.h
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mlx4/srq.c
drivers/infiniband/hw/mthca/Kconfig
drivers/infiniband/hw/mthca/mthca_allocator.c
drivers/infiniband/hw/mthca/mthca_eq.c
drivers/infiniband/ulp/ipoib/Kconfig
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/iser/Kconfig
drivers/infiniband/ulp/srp/Kconfig
drivers/input/mouse/psmouse.h
drivers/isdn/hisax/bkm_a8.c
drivers/macintosh/windfarm_core.c
drivers/macintosh/windfarm_smu_sat.c
drivers/md/Kconfig
drivers/md/Makefile
drivers/md/dm-bio-list.h
drivers/md/dm-crypt.c
drivers/md/dm-delay.c
drivers/md/dm-exception-store.c
drivers/md/dm-io.c
drivers/md/dm-mpath-rdac.c [new file with mode: 0644]
drivers/md/dm-mpath.c
drivers/md/dm-raid1.c
drivers/md/dm-round-robin.c
drivers/md/dm-snap.c
drivers/md/dm-snap.h
drivers/md/dm.c
drivers/md/dm.h
drivers/md/kcopyd.c
drivers/md/md.c
drivers/md/raid5.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/video/meye.c
drivers/misc/asus-laptop.c
drivers/misc/msi-laptop.c
drivers/mmc/host/pxamci.h
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/atl1/atl1.h
drivers/net/atl1/atl1_main.c
drivers/net/bnx2.c
drivers/net/cassini.c
drivers/net/cxgb3/version.h
drivers/net/dl2k.c
drivers/net/dl2k.h
drivers/net/dm9000.c
drivers/net/e100.c
drivers/net/e1000/e1000_main.c
drivers/net/forcedeth.c
drivers/net/ibmveth.c
drivers/net/macvlan.c [new file with mode: 0644]
drivers/net/mlx4/fw.c
drivers/net/mlx4/fw.h
drivers/net/mlx4/main.c
drivers/net/mlx4/mlx4.h
drivers/net/mlx4/qp.c
drivers/net/mlx4/srq.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/starfire.c
drivers/net/sundance.c
drivers/net/sunhme.c
drivers/net/tg3.c
drivers/net/tlan.c
drivers/net/tulip/de4x5.c
drivers/net/tulip/dmfe.c
drivers/net/tulip/tulip_core.c
drivers/net/tulip/xircom_cb.c
drivers/net/tulip/xircom_tulip_cb.c
drivers/net/typhoon.c
drivers/net/via-rhine.c
drivers/net/via-velocity.c
drivers/net/wan/pc300_drv.c
drivers/net/wan/pc300too.c
drivers/net/wan/pci200syn.c
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/hostap/hostap_pci.c
drivers/net/wireless/hostap/hostap_plx.c
drivers/net/wireless/prism54/islpci_hotplug.c
drivers/parisc/pdc_stable.c
drivers/pci/Makefile
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_ibm.c
drivers/pci/hotplug/cpci_hotplug_core.c
drivers/pci/hotplug/cpci_hotplug_pci.c
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/pci-acpi.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pcie/aer/Kconfig
drivers/pci/pcie/aer/Makefile
drivers/pci/pcie/aer/aerdrv.c
drivers/pci/pcie/aer/aerdrv.h
drivers/pci/pcie/aer/aerdrv_acpi.c
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/probe.c
drivers/pci/proc.c
drivers/pci/quirks.c
drivers/pci/rom.c
drivers/pci/search.c
drivers/pci/setup-bus.c
drivers/pci/syscall.c
drivers/pcmcia/socket_sysfs.c
drivers/rapidio/rio-sysfs.c
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-ds1742.c
drivers/rtc/rtc-vr41xx.c
drivers/rtc/rtc-x1205.c
drivers/s390/cio/chp.c
drivers/s390/net/qeth_sys.c
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/arcmsr/arcmsr_attr.c
drivers/scsi/ipr.c
drivers/scsi/ips.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/nsp32.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_init.c
drivers/serial/Kconfig
drivers/serial/bfin_5xx.c
drivers/serial/jsm/jsm_driver.c
drivers/serial/vr41xx_siu.c
drivers/spi/at25.c
drivers/tc/zs.c
drivers/usb/Kconfig
drivers/usb/Makefile
drivers/usb/atm/cxacru.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/usblp.c
drivers/usb/core/Kconfig
drivers/usb/core/config.c
drivers/usb/core/devices.c
drivers/usb/core/driver.c
drivers/usb/core/file.c
drivers/usb/core/generic.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/hcd.h
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/core/quirks.c
drivers/usb/core/sysfs.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/fsl_usb2_udc.c
drivers/usb/gadget/fsl_usb2_udc.h
drivers/usb/gadget/gadget_chips.h
drivers/usb/gadget/gmidi.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/goku_udc.h
drivers/usb/gadget/inode.c
drivers/usb/gadget/lh7a40x_udc.c
drivers/usb/gadget/m66592-udc.c [new file with mode: 0644]
drivers/usb/gadget/m66592-udc.h [new file with mode: 0644]
drivers/usb/gadget/net2280.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/gadget/pxa2xx_udc.h
drivers/usb/gadget/rndis.c
drivers/usb/gadget/s3c2410_udc.c [new file with mode: 0644]
drivers/usb/gadget/s3c2410_udc.h [new file with mode: 0644]
drivers/usb/gadget/serial.c
drivers/usb/gadget/zero.c
drivers/usb/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-mem.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-ppc-soc.c [new file with mode: 0644]
drivers/usb/host/ehci-ps3.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci.h
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-mem.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-pnx4008.c
drivers/usb/host/ohci-ps3.c
drivers/usb/host/ohci.h
drivers/usb/host/r8a66597-hcd.c [new file with mode: 0644]
drivers/usb/host/r8a66597.h [new file with mode: 0644]
drivers/usb/host/uhci-hcd.c
drivers/usb/misc/adutux.c
drivers/usb/misc/auerswald.c
drivers/usb/misc/berry_charge.c
drivers/usb/misc/idmouse.c
drivers/usb/misc/iowarrior.c
drivers/usb/misc/ldusb.c
drivers/usb/misc/legousbtower.c
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/sisusbvga/sisusb_con.c
drivers/usb/misc/sisusbvga/sisusb_init.h
drivers/usb/misc/usblcd.c
drivers/usb/mon/mon_bin.c
drivers/usb/mon/mon_main.c
drivers/usb/mon/mon_text.c
drivers/usb/mon/usb_mon.h
drivers/usb/serial/Kconfig
drivers/usb/serial/Makefile
drivers/usb/serial/aircable.c
drivers/usb/serial/airprime.c
drivers/usb/serial/ark3116.c
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/empeg.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/generic.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_fw_down3.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/io_usbvend.h
drivers/usb/serial/ipaq.c
drivers/usb/serial/ipw.c
drivers/usb/serial/ir-usb.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan.h
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/keyspan_usa67msg.h [new file with mode: 0644]
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/mct_u232.h
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/navman.c
drivers/usb/serial/omninet.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c [new file with mode: 0644]
drivers/usb/serial/oti6858.h [new file with mode: 0644]
drivers/usb/serial/pl2303.c
drivers/usb/serial/safe_serial.c
drivers/usb/serial/sierra.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/visor.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/usb.c
drivers/usb/storage/usb.h
drivers/usb/usb-skeleton.c
drivers/video/aty/radeon_base.c
drivers/video/backlight/backlight.c
drivers/video/backlight/lcd.c
drivers/video/console/Kconfig
drivers/video/kyro/STG4000InitDevice.c
drivers/video/matrox/matroxfb_base.c
drivers/video/matrox/matroxfb_crtc2.h
drivers/video/sis/sis_main.c
drivers/video/sstfb.c
drivers/video/tgafb.c
drivers/w1/slaves/w1_ds2433.c
drivers/w1/slaves/w1_therm.c
drivers/w1/w1.c
drivers/zorro/zorro-sysfs.c
fs/debugfs/inode.c
fs/ecryptfs/main.c
fs/lockd/host.c
fs/lockd/mon.c
fs/lockd/svc.c
fs/nfs/Makefile
fs/nfs/client.c
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/mount_clnt.c
fs/nfs/nfs2xdr.c
fs/nfs/nfs3proc.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/nfsroot.c
fs/nfs/pagelist.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4state.c
fs/nfsd/vfs.c
fs/ocfs2/cluster/masklog.c
fs/partitions/check.c
fs/splice.c
fs/sysfs/bin.c
fs/sysfs/dir.c
fs/sysfs/file.c
fs/sysfs/group.c
fs/sysfs/inode.c
fs/sysfs/mount.c
fs/sysfs/symlink.c
fs/sysfs/sysfs.h
include/asm-alpha/pci.h
include/asm-arm/Kbuild
include/asm-arm/arch-at91/at91_dbgu.h
include/asm-arm/arch-at91/at91x40.h [new file with mode: 0644]
include/asm-arm/arch-at91/cpu.h
include/asm-arm/arch-at91/hardware.h
include/asm-arm/arch-at91/timex.h
include/asm-arm/arch-at91/uncompress.h
include/asm-arm/arch-davinci/clock.h [new file with mode: 0644]
include/asm-arm/arch-davinci/gpio.h [new file with mode: 0644]
include/asm-arm/arch-davinci/hardware.h
include/asm-arm/arch-davinci/mux.h [new file with mode: 0644]
include/asm-arm/arch-imx/gpio.h [new file with mode: 0644]
include/asm-arm/arch-imx/imx-regs.h
include/asm-arm/arch-iop13xx/adma.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/iop13xx.h
include/asm-arm/arch-iop32x/adma.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/adma.h [new file with mode: 0644]
include/asm-arm/arch-ixp4xx/ixdp425.h
include/asm-arm/arch-ixp4xx/udc.h
include/asm-arm/arch-ixp4xx/uncompress.h
include/asm-arm/arch-ks8695/gpio.h [new file with mode: 0644]
include/asm-arm/arch-pxa/dma.h
include/asm-arm/arch-pxa/entry-macro.S
include/asm-arm/arch-pxa/hardware.h
include/asm-arm/arch-pxa/irqs.h
include/asm-arm/arch-pxa/pm.h
include/asm-arm/arch-pxa/pxa-regs.h
include/asm-arm/arch-pxa/udc.h
include/asm-arm/elf.h
include/asm-arm/hardware/iop3xx-adma.h [new file with mode: 0644]
include/asm-arm/hardware/iop3xx.h
include/asm-arm/hardware/iop_adma.h [new file with mode: 0644]
include/asm-arm/hwcap.h [new file with mode: 0644]
include/asm-arm/pci.h
include/asm-arm/ptrace.h
include/asm-blackfin/Kbuild
include/asm-blackfin/bfin-global.h
include/asm-blackfin/cplbinit.h
include/asm-blackfin/fixed_code.h [new file with mode: 0644]
include/asm-blackfin/gpio.h
include/asm-blackfin/hardirq.h
include/asm-blackfin/kgdb.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/dma.h
include/asm-blackfin/mach-bf533/portmux.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/dma.h
include/asm-blackfin/mach-bf537/portmux.h [new file with mode: 0644]
include/asm-blackfin/mach-bf548/anomaly.h [new file with mode: 0644]
include/asm-blackfin/mach-bf548/bf548.h [new file with mode: 0644]
include/asm-blackfin/mach-bf548/bfin_serial_5xx.h [new file with mode: 0644]
include/asm-blackfin/mach-bf548/blackfin.h [new file with mode: 0644]
include/asm-blackfin/mach-bf548/cdefBF54x_base.h
include/asm-blackfin/mach-bf548/defBF542.h
include/asm-blackfin/mach-bf548/defBF544.h
include/asm-blackfin/mach-bf548/defBF548.h
include/asm-blackfin/mach-bf548/defBF549.h
include/asm-blackfin/mach-bf548/defBF54x_base.h
include/asm-blackfin/mach-bf548/dma.h [new file with mode: 0644]
include/asm-blackfin/mach-bf548/gpio.h [new file with mode: 0644]
include/asm-blackfin/mach-bf548/irq.h [new file with mode: 0644]
include/asm-blackfin/mach-bf548/mem_init.h [new file with mode: 0644]
include/asm-blackfin/mach-bf548/mem_map.h [new file with mode: 0644]
include/asm-blackfin/mach-bf548/portmux.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/cdefBF561.h
include/asm-blackfin/mach-bf561/dma.h
include/asm-blackfin/mach-bf561/portmux.h [new file with mode: 0644]
include/asm-blackfin/mach-common/cdef_LPBlackfin.h
include/asm-blackfin/mman.h
include/asm-blackfin/page.h
include/asm-blackfin/portmux.h [new file with mode: 0644]
include/asm-blackfin/trace.h [new file with mode: 0644]
include/asm-cris/pci.h
include/asm-frv/pci.h
include/asm-h8300/pci.h
include/asm-i386/boot.h
include/asm-i386/bootparam.h [new file with mode: 0644]
include/asm-i386/cpufeature.h
include/asm-i386/e820.h
include/asm-i386/pci.h
include/asm-i386/processor.h
include/asm-i386/required-features.h
include/asm-i386/setup.h
include/asm-ia64/mca.h
include/asm-ia64/pci.h
include/asm-ia64/sn/sn_sal.h
include/asm-m68k/pci.h
include/asm-m68knommu/pci.h
include/asm-mips/compat.h
include/asm-mips/io.h
include/asm-mips/irq.h
include/asm-mips/mach-tx49xx/ioremap.h
include/asm-mips/mipsregs.h
include/asm-mips/pci.h
include/asm-mips/rtc.h [deleted file]
include/asm-mips/tlbdebug.h
include/asm-mips/vr41xx/giu.h
include/asm-mips/vr41xx/siu.h
include/asm-parisc/pci.h
include/asm-powerpc/dma-mapping.h
include/asm-powerpc/pci.h
include/asm-ppc/pci.h
include/asm-sh/pci.h
include/asm-sh64/pci.h
include/asm-sparc/pci.h
include/asm-sparc64/pci.h
include/asm-v850/pci.h
include/asm-v850/rte_cb.h
include/asm-x86_64/alternative.h
include/asm-x86_64/boot.h
include/asm-x86_64/bootparam.h [new file with mode: 0644]
include/asm-x86_64/cpufeature.h
include/asm-x86_64/e820.h
include/asm-x86_64/pci.h
include/asm-x86_64/processor.h
include/asm-x86_64/required-features.h [new file with mode: 0644]
include/asm-x86_64/segment.h
include/asm-xtensa/pci.h
include/linux/aer.h
include/linux/async_tx.h [new file with mode: 0644]
include/linux/ata.h
include/linux/debugfs.h
include/linux/device.h
include/linux/dmaengine.h
include/linux/dmi.h
include/linux/edd.h
include/linux/i2c.h
include/linux/idr.h
include/linux/if_macvlan.h [new file with mode: 0644]
include/linux/if_vlan.h
include/linux/kobject.h
include/linux/libata.h
include/linux/lockd/lockd.h
include/linux/mlx4/device.h
include/linux/mlx4/qp.h
include/linux/netdevice.h
include/linux/nfs4.h
include/linux/nfs4_mount.h
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_mount.h
include/linux/nfs_page.h
include/linux/nfs_xdr.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/pm.h
include/linux/raid/raid5.h
include/linux/raid/xor.h
include/linux/screen_info.h
include/linux/security.h
include/linux/serio.h
include/linux/sunrpc/auth.h
include/linux/sunrpc/auth_gss.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/gss_api.h
include/linux/sunrpc/rpc_pipe_fs.h
include/linux/sunrpc/sched.h
include/linux/sunrpc/svcsock.h
include/linux/sunrpc/xprt.h
include/linux/sysdev.h
include/linux/sysfs.h
include/linux/topology.h
include/linux/usb.h
include/linux/usb/Kbuild
include/linux/usb/gadgetfs.h [moved from include/linux/usb_gadgetfs.h with 74% similarity]
include/linux/usb/quirks.h
include/linux/usb/serial.h
include/linux/usb_gadget.h
include/rdma/ib_cm.h
include/rdma/ib_mad.h
kernel/module.c
kernel/params.c
kernel/relay.c
kernel/sched.c
kernel/sched_debug.c
kernel/sysctl.c
lib/idr.c
lib/kobject.c
mm/mmap.c
mm/mremap.c
mm/nommu.c
net/8021q/vlan.c
net/8021q/vlan.h
net/8021q/vlan_dev.c
net/bridge/br_sysfs_br.c
net/bridge/br_sysfs_if.c
net/core/dev.c
net/core/dev_mcast.c
net/ipv4/tcp.c
net/ipv4/tcp_probe.c
net/rfkill/rfkill-input.c
net/sunrpc/auth.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_spkm3_mech.c
net/sunrpc/auth_null.c
net/sunrpc/auth_unix.c
net/sunrpc/clnt.c
net/sunrpc/rpc_pipe.c
net/sunrpc/rpcb_clnt.c
net/sunrpc/sched.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svcsock.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c
security/dummy.c
security/security.c
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/include/av_perm_to_string.h
security/selinux/include/av_permissions.h
security/selinux/include/avc.h
security/selinux/include/class_to_string.h
security/selinux/include/flask.h
security/selinux/include/security.h
security/selinux/selinuxfs.c
security/selinux/ss/policydb.c
security/selinux/ss/services.c
sound/oss/emu10k1/main.c
sound/oss/es1371.c
sound/pci/ali5451/ali5451.c
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/au88x0/au88x0.c
sound/pci/ca0106/ca0106.h
sound/pci/ca0106/ca0106_main.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/ens1370.c
sound/pci/fm801.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/ymfpci/ymfpci_main.c

index f9937add033d833e869fb996565bb74ff2f5233d..9734577d171154630f49be83779863ef875d6b7e 100644 (file)
@@ -39,3 +39,16 @@ Description:
                If you want to suspend a device immediately but leave it
                free to wake up in response to I/O requests, you should
                write "0" to power/autosuspend.
+
+What:          /sys/bus/usb/devices/.../power/persist
+Date:          May 2007
+KernelVersion: 2.6.23
+Contact:       Alan Stern <stern@rowland.harvard.edu>
+Description:
+               If CONFIG_USB_PERSIST is set, then each USB device directory
+               will contain a file named power/persist.  The file holds a
+               boolean value (0 or 1) indicating whether or not the
+               "USB-Persist" facility is enabled for the device.  Since the
+               facility is inherently dangerous, it is disabled by default
+               for all devices except hubs.  For more information, see
+               Documentation/usb/persist.txt.
index 028614cdd0624291f630d3cdda899cf02335ed2b..e07f2530326b3afcbe69e77720833435e75e57d7 100644 (file)
@@ -664,109 +664,6 @@ It is that simple.
 Well, not for some odd devices.  See the next section for information
 about that.
 
-       DAC Addressing for Address Space Hungry Devices
-
-There exists a class of devices which do not mesh well with the PCI
-DMA mapping API.  By definition these "mappings" are a finite
-resource.  The number of total available mappings per bus is platform
-specific, but there will always be a reasonable amount.
-
-What is "reasonable"?  Reasonable means that networking and block I/O
-devices need not worry about using too many mappings.
-
-As an example of a problematic device, consider compute cluster cards.
-They can potentially need to access gigabytes of memory at once via
-DMA.  Dynamic mappings are unsuitable for this kind of access pattern.
-
-To this end we've provided a small API by which a device driver
-may use DAC cycles to directly address all of physical memory.
-Not all platforms support this, but most do.  It is easy to determine
-whether the platform will work properly at probe time.
-
-First, understand that there may be a SEVERE performance penalty for
-using these interfaces on some platforms.  Therefore, you MUST only
-use these interfaces if it is absolutely required.  %99 of devices can
-use the normal APIs without any problems.
-
-Note that for streaming type mappings you must either use these
-interfaces, or the dynamic mapping interfaces above.  You may not mix
-usage of both for the same device.  Such an act is illegal and is
-guaranteed to put a banana in your tailpipe.
-
-However, consistent mappings may in fact be used in conjunction with
-these interfaces.  Remember that, as defined, consistent mappings are
-always going to be SAC addressable.
-
-The first thing your driver needs to do is query the PCI platform
-layer if it is capable of handling your devices DAC addressing
-capabilities:
-
-       int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask);
-
-You may not use the following interfaces if this routine fails.
-
-Next, DMA addresses using this API are kept track of using the
-dma64_addr_t type.  It is guaranteed to be big enough to hold any
-DAC address the platform layer will give to you from the following
-routines.  If you have consistent mappings as well, you still
-use plain dma_addr_t to keep track of those.
-
-All mappings obtained here will be direct.  The mappings are not
-translated, and this is the purpose of this dialect of the DMA API.
-
-All routines work with page/offset pairs.  This is the _ONLY_ way to 
-portably refer to any piece of memory.  If you have a cpu pointer
-(which may be validly DMA'd too) you may easily obtain the page
-and offset using something like this:
-
-       struct page *page = virt_to_page(ptr);
-       unsigned long offset = offset_in_page(ptr);
-
-Here are the interfaces:
-
-       dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-                                        struct page *page,
-                                        unsigned long offset,
-                                        int direction);
-
-The DAC address for the tuple PAGE/OFFSET are returned.  The direction
-argument is the same as for pci_{map,unmap}_single().  The same rules
-for cpu/device access apply here as for the streaming mapping
-interfaces.  To reiterate:
-
-       The cpu may touch the buffer before pci_dac_page_to_dma.
-       The device may touch the buffer after pci_dac_page_to_dma
-       is made, but the cpu may NOT.
-
-When the DMA transfer is complete, invoke:
-
-       void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-                                            dma64_addr_t dma_addr,
-                                            size_t len, int direction);
-
-This must be done before the CPU looks at the buffer again.
-This interface behaves identically to pci_dma_sync_{single,sg}_for_cpu().
-
-And likewise, if you wish to let the device get back at the buffer after
-the cpu has read/written it, invoke:
-
-       void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-                                               dma64_addr_t dma_addr,
-                                               size_t len, int direction);
-
-before letting the device access the DMA area again.
-
-If you need to get back to the PAGE/OFFSET tuple from a dma64_addr_t
-the following interfaces are provided:
-
-       struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-                                        dma64_addr_t dma_addr);
-       unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-                                           dma64_addr_t dma_addr);
-
-This is possible with the DAC interfaces purely because they are
-not translated in any way.
-
                Optimizing Unmap State Space Consumption
 
 On many platforms, pci_unmap_{single,page}() is simply a nop.
index 8c5698a8c2e1e071060511353ce457da215f0e5e..46bcff2849bddbffad2817304bbc8964b1cba6e5 100644 (file)
@@ -643,6 +643,60 @@ X!Idrivers/video/console/fonts.c
 !Edrivers/spi/spi.c
   </chapter>
 
+  <chapter id="i2c">
+     <title>I<superscript>2</superscript>C and SMBus Subsystem</title>
+
+     <para>
+       I<superscript>2</superscript>C (or without fancy typography, "I2C")
+       is an acronym for the "Inter-IC" bus, a simple bus protocol which is
+       widely used where low data rate communications suffice.
+       Since it's also a licensed trademark, some vendors use another
+       name (such as "Two-Wire Interface", TWI) for the same bus.
+       I2C only needs two signals (SCL for clock, SDA for data), conserving
+       board real estate and minimizing signal quality issues.
+       Most I2C devices use seven bit addresses, and bus speeds of up
+       to 400 kHz; there's a high speed extension (3.4 MHz) that's not yet
+       found wide use.
+       I2C is a multi-master bus; open drain signaling is used to
+       arbitrate between masters, as well as to handshake and to
+       synchronize clocks from slower clients.
+     </para>
+
+     <para>
+       The Linux I2C programming interfaces support only the master
+       side of bus interactions, not the slave side.
+       The programming interface is structured around two kinds of driver,
+       and two kinds of device.
+       An I2C "Adapter Driver" abstracts the controller hardware; it binds
+       to a physical device (perhaps a PCI device or platform_device) and
+       exposes a <structname>struct i2c_adapter</structname> representing
+       each I2C bus segment it manages.
+       On each I2C bus segment will be I2C devices represented by a
+       <structname>struct i2c_client</structname>.  Those devices will
+       be bound to a <structname>struct i2c_driver</structname>,
+       which should follow the standard Linux driver model.
+       (At this writing, a legacy model is more widely used.)
+       There are functions to perform various I2C protocol operations; at
+       this writing all such functions are usable only from task context.
+     </para>
+
+     <para>
+       The System Management Bus (SMBus) is a sibling protocol.  Most SMBus
+       systems are also I2C conformant.  The electrical constraints are
+       tighter for SMBus, and it standardizes particular protocol messages
+       and idioms.  Controllers that support I2C can also support most
+       SMBus operations, but SMBus controllers don't support all the protocol
+       options that an I2C controller will.
+       There are functions to perform various SMBus protocol operations,
+       either using I2C primitives or by issuing SMBus commands to
+       i2c_adapter devices which don't support those I2C operations.
+     </para>
+
+!Iinclude/linux/i2c.h
+!Fdrivers/i2c/i2c-boardinfo.c i2c_register_board_info
+!Edrivers/i2c/i2c-core.c
+  </chapter>
+
   <chapter id="splice">
       <title>splice API</title>
   <para>)
@@ -654,4 +708,5 @@ X!Idrivers/video/console/fonts.c
 !Ffs/splice.c
   </chapter>
 
+
 </book>
diff --git a/Documentation/blackfin/kgdb.txt b/Documentation/blackfin/kgdb.txt
new file mode 100644 (file)
index 0000000..84f6a48
--- /dev/null
@@ -0,0 +1,155 @@
+                       A Simple Guide to Configure KGDB
+
+                       Sonic Zhang <sonic.zhang@analog.com>
+                               Aug. 24th 2006
+
+
+This KGDB patch enables the kernel developer to do source level debugging on
+the kernel for the Blackfin architecture.  The debugging works over either the
+ethernet interface or one of the uarts.  Both software breakpoints and
+hardware breakpoints are supported in this version.
+http://docs.blackfin.uclinux.org/doku.php?id=kgdb
+
+
+2 known issues:
+1. This bug:
+       http://blackfin.uclinux.org/tracker/index.php?func=detail&aid=544&group_id=18&atid=145
+   The GDB client for Blackfin uClinux causes incorrect values of local
+   variables to be displayed when the user breaks the running of kernel in GDB.
+2. Because of a hardware bug in Blackfin 533 v1.0.3:
+       05000067 - Watchpoints (Hardware Breakpoints) are not supported
+   Hardware breakpoints cannot be set properly.
+
+
+Debug over Ethernet:
+1. Compile and install the cross platform version of gdb for blackfin, which
+   can be found at $(BINROOT)/bfin-elf-gdb.
+
+2. Apply this patch to the 2.6.x kernel.  Select the menuconfig option under
+   "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
+   With this selected, option "Full Symbolic/Source Debugging support" and 
+   "Compile the kernel with frame pointers" are also selected.
+
+3. Select option "KGDB: connect over (Ethernet)".  Add "kgdboe=@target-IP/,@host-IP/" to
+   the option "Compiled-in Kernel Boot Parameter" under "Kernel hacking".
+
+4. Connect minicom to the serial port and boot the kernel image.
+
+5. Configure the IP "/> ifconfig eth0 target-IP"
+
+6. Start GDB client "bfin-elf-gdb vmlinux".
+
+7. Connect to the target "(gdb) target remote udp:target-IP:6443".
+
+8. Set software breakpoint "(gdb) break sys_open".
+
+9. Continue "(gdb) c".
+
+10. Run ls in the target console "/> ls".
+
+11. Breakpoint hits. "Breakpoint 1: sys_open(..."
+
+12. Display local variables and function paramters.
+    (*) This operation gives wrong results, see known issue 1.
+
+13. Single stepping "(gdb) si".
+
+14. Remove breakpoint 1. "(gdb) del 1"
+
+15. Set hardware breakpoint "(gdb) hbreak sys_open".
+
+16. Continue "(gdb) c".
+
+17. Run ls in the target console "/> ls".
+
+18. Hardware breakpoint hits. "Breakpoint 1: sys_open(...".
+    (*) This hardware breakpoint will not be hit, see known issue 2.
+
+19. Continue "(gdb) c".
+
+20. Interrupt the target in GDB "Ctrl+C".
+
+21. Detach from the target "(gdb) detach".
+
+22. Exit GDB "(gdb) quit".
+
+
+Debug over the UART:
+
+1. Compile and install the cross platform version of gdb for blackfin, which
+   can be found at $(BINROOT)/bfin-elf-gdb.
+
+2. Apply this patch to the 2.6.x kernel.  Select the menuconfig option under
+   "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
+   With this selected, option "Full Symbolic/Source Debugging support" and 
+   "Compile the kernel with frame pointers" are also selected.
+
+3. Select option "KGDB: connect over (UART)".  Set "KGDB: UART port number" to be
+   a different one from the console.  Don't forget to change the mode of
+   blackfin serial driver to PIO.  Otherwise kgdb works incorrectly on UART.
+4. If you want connect to kgdb when the kernel boots, enable
+   "KGDB: Wait for gdb connection early" 
+
+5. Compile kernel.
+
+6. Connect minicom to the serial port of the console and boot the kernel image.
+
+7. Start GDB client "bfin-elf-gdb vmlinux".
+
+8. Set the baud rate in GDB "(gdb) set remotebaud 57600".
+
+9. Connect to the target on the second serial port "(gdb) target remote /dev/ttyS1".
+
+10. Set software breakpoint "(gdb) break sys_open".
+
+11. Continue "(gdb) c". 
+
+12. Run ls in the target console "/> ls". 
+
+13. A breakpoint is hit. "Breakpoint 1: sys_open(..."
+
+14. All other operations are the same as that in KGDB over Ethernet. 
+
+
+Debug over the same UART as console:
+
+1. Compile and install the cross platform version of gdb for blackfin, which
+   can be found at $(BINROOT)/bfin-elf-gdb.
+
+2. Apply this patch to the 2.6.x kernel.  Select the menuconfig option under
+   "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
+   With this selected, option "Full Symbolic/Source Debugging support" and 
+   "Compile the kernel with frame pointers" are also selected.
+
+3. Select option "KGDB: connect over UART".  Set "KGDB: UART port number" to console.
+   Don't forget to change the mode of blackfin serial driver to PIO.
+   Otherwise kgdb works incorrectly on UART.
+4. If you want connect to kgdb when the kernel boots, enable
+   "KGDB: Wait for gdb connection early" 
+
+5. Connect minicom to the serial port and boot the kernel image. 
+
+6. (Optional) Ask target to wait for gdb connection by entering Ctrl+A. In minicom, you should enter Ctrl+A+A.
+
+7. Start GDB client "bfin-elf-gdb vmlinux".
+
+8. Set the baud rate in GDB "(gdb) set remotebaud 57600".
+
+9. Connect to the target "(gdb) target remote /dev/ttyS0".
+
+10. Set software breakpoint "(gdb) break sys_open".
+
+11. Continue "(gdb) c". Then enter Ctrl+C twice to stop GDB connection.
+
+12. Run ls in the target console "/> ls". Dummy string can be seen on the console.
+
+13. Then connect the gdb to target again. "(gdb) target remote /dev/ttyS0".
+    Now you will find a breakpoint is hit. "Breakpoint 1: sys_open(..."
+
+14. All other operations are the same as that in KGDB over Ethernet.  The only
+    difference is that after continue command in GDB, please stop GDB
+    connection by 2 "Ctrl+C"s and connect again after breakpoints are hit or
+    Ctrl+A is entered.
index 062fc2e79c8610034a5555c5108f75c1430e4b97..092c65dd35c2e9dd4fdf4f24cd6a6b1f8e64bc84 100644 (file)
@@ -196,28 +196,6 @@ Who:   Adrian Bunk <bunk@stusta.de>
 
 ---------------------------
 
-What:  ACPI hooks (X86_SPEEDSTEP_CENTRINO_ACPI) in speedstep-centrino driver
-When:  December 2006
-Why:   Speedstep-centrino driver with ACPI hooks and acpi-cpufreq driver are
-       functionally very much similar. They talk to ACPI in same way. Only
-       difference between them is the way they do frequency transitions.
-       One uses MSRs and the other one uses IO ports. Functionaliy of
-       speedstep_centrino with ACPI hooks is now merged into acpi-cpufreq.
-       That means one common driver will support all Intel Enhanced Speedstep
-       capable CPUs. That means less confusion over name of
-       speedstep-centrino driver (with that driver supposed to be used on
-       non-centrino platforms). That means less duplication of code and
-       less maintenance effort and no possibility of these two drivers
-       going out of sync.
-       Current users of speedstep_centrino with ACPI hooks are requested to
-       switch over to acpi-cpufreq driver. speedstep-centrino will continue
-       to work using older non-ACPI static table based scheme even after this
-       date.
-
-Who:   Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
-
----------------------------
-
 What:  /sys/firmware/acpi/namespace
 When:  2.6.21
 Why:   The ACPI namespace is effectively the symbol list for
@@ -311,6 +289,13 @@ Who:  Tejun Heo <htejun@gmail.com>
 
 ---------------------------
 
+What:  Legacy RTC drivers (under drivers/i2c/chips)
+When:  November 2007
+Why:   Obsolete. We have a RTC subsystem with better drivers.
+Who:   Jean Delvare <khali@linux-fr.org>
+
+---------------------------
+
 What:  iptables SAME target
 When:  1.1. 2008
 Files: net/ipv4/netfilter/ipt_SAME.c, include/linux/netfilter_ipv4/ipt_SAME.h
index 4994f1f28f8ce23bf56ec61976cbefe19c008d41..fba943aacf93e2a8b040996bf26c408ee737e1a3 100644 (file)
@@ -78,6 +78,7 @@ static CLASS_DEVICE_ATTR(loading, 0644,
                         firmware_loading_show, firmware_loading_store);
 
 static ssize_t firmware_data_read(struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
                                  char *buffer, loff_t offset, size_t count)
 {
        struct class_device *class_dev = to_class_dev(kobj);
@@ -88,6 +89,7 @@ static ssize_t firmware_data_read(struct kobject *kobj,
        return count;
 }
 static ssize_t firmware_data_write(struct kobject *kobj,
+                                  struct bin_attribute *bin_attr,
                                   char *buffer, loff_t offset, size_t count)
 {
        struct class_device *class_dev = to_class_dev(kobj);
index c34f0db78a30f9f66b22f055f92cd95ae024c6dc..fe6406f2f9a66ac9c96216c097f02b0b7b107816 100644 (file)
@@ -5,8 +5,8 @@ Supported adapters:
     '810' and '810E' chipsets)
   * Intel 82801BA (ICH2 - part of the '815E' chipset)
   * Intel 82801CA/CAM (ICH3)
-  * Intel 82801DB (ICH4) (HW PEC supported, 32 byte buffer not supported)
-  * Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported)
+  * Intel 82801DB (ICH4) (HW PEC supported)
+  * Intel 82801EB/ER (ICH5) (HW PEC supported)
   * Intel 6300ESB
   * Intel 82801FB/FR/FW/FRW (ICH6)
   * Intel 82801G (ICH7)
index 7cbe43fa2701dfb875a7eae69754ecb557e5c043..fa0c786a8bf5a787e6a980dd9dbeef9c283d7b41 100644 (file)
@@ -6,7 +6,7 @@ Supported adapters:
     Datasheet: Publicly available at the Intel website
   * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges
     Datasheet: Only available via NDA from ServerWorks
-  * ATI IXP200, IXP300, IXP400 and SB600 southbridges
+  * ATI IXP200, IXP300, IXP400, SB600 and SB700 southbridges
     Datasheet: Not publicly available
   * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
     Datasheet: Publicly available at the SMSC website http://www.smsc.com
diff --git a/Documentation/i2c/busses/i2c-taos-evm b/Documentation/i2c/busses/i2c-taos-evm
new file mode 100644 (file)
index 0000000..9146e33
--- /dev/null
@@ -0,0 +1,46 @@
+Kernel driver i2c-taos-evm
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+This is a driver for the evaluation modules for TAOS I2C/SMBus chips.
+The modules include an SMBus master with limited capabilities, which can
+be controlled over the serial port. Virtually all evaluation modules
+are supported, but a few lines of code need to be added for each new
+module to instantiate the right I2C chip on the bus. Obviously, a driver
+for the chip in question is also needed.
+
+Currently supported devices are:
+
+* TAOS TSL2550 EVM
+
+For addtional information on TAOS products, please see
+  http://www.taosinc.com/
+
+
+Using this driver
+-----------------
+
+In order to use this driver, you'll need the serport driver, and the
+inputattach tool, which is part of the input-utils package. The following
+commands will tell the kernel that you have a TAOS EVM on the first
+serial port:
+
+# modprobe serport
+# inputattach --taos-evm /dev/ttyS0
+
+
+Technical details
+-----------------
+
+Only 4 SMBus transaction types are supported by the TAOS evaluation
+modules:
+* Receive Byte
+* Send Byte
+* Read Byte
+* Write Byte
+
+The communication protocol is text-based and pretty simple. It is
+described in a PDF document on the CD which comes with the evaluation
+module. The communication is rather slow, because the serial port has
+to operate at 1200 bps. However, I don't think this is a big concern in
+practice, as these modules are meant for evaluation and testing only.
index 96fec562a8e9020fc92a5d8c1de5676bda953cf8..a0cd8af2f40806a53ac2dc1841be8530d4e59992 100644 (file)
@@ -99,7 +99,7 @@ And then read the data
 
   or
 
-  count = i2c_smbus_read_i2c_block_data(fd, 0x84, buffer);
+  count = i2c_smbus_read_i2c_block_data(fd, 0x84, 16, buffer);
 
 The block read should read 16 bytes.
 0x84 is the block read command.
diff --git a/Documentation/i2c/chips/x1205 b/Documentation/i2c/chips/x1205
deleted file mode 100644 (file)
index 09407c9..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-Kernel driver x1205
-===================
-
-Supported chips:
-  * Xicor X1205 RTC
-    Prefix: 'x1205'
-    Addresses scanned: none
-    Datasheet: http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html
-
-Authors:
-       Karen Spearel <kas11@tampabay.rr.com>,
-       Alessandro Zummo <a.zummo@towertech.it>
-
-Description
------------
-
-This module aims to provide complete access to the Xicor X1205 RTC.
-Recently Xicor has merged with Intersil, but the chip is
-still sold under the Xicor brand.
-
-This chip is located at address 0x6f and uses a 2-byte register addressing.
-Two bytes need to be written to read a single register, while most
-other chips just require one and take the second one as the data
-to be written. To prevent corrupting unknown chips, the user must
-explicitely set the probe parameter.
-
-example:
-
-modprobe x1205 probe=0,0x6f
-
-The module supports one more option, hctosys, which is used to set the
-software clock from the x1205. On systems where the x1205 is the
-only hardware rtc, this parameter could be used to achieve a correct
-date/time earlier in the system boot sequence.
-
-example:
-
-modprobe x1205 probe=0,0x6f hctosys=1
index aea60bf7e8f0847370e17beec79880307754a5d5..003c7319b8c7a6dbae0881ae513474eea86f727b 100644 (file)
@@ -67,7 +67,6 @@ i2c-proc: The /proc/sys/dev/sensors interface for device (client) drivers
 Algorithm drivers
 -----------------
 
-i2c-algo-8xx:    An algorithm for CPM's I2C device in Motorola 8xx processors (NOT BUILT BY DEFAULT)
 i2c-algo-bit:    A bit-banging algorithm
 i2c-algo-pcf:    A PCF 8584 style algorithm
 i2c-algo-ibm_ocp: An algorithm for the I2C device in IBM 4xx processors (NOT BUILT BY DEFAULT)
@@ -81,6 +80,5 @@ i2c-pcf-epp:     PCF8584 on a EPP parallel port (uses i2c-algo-pcf) (NOT mkpatch
 i2c-philips-par: Philips style parallel port adapter (uses i2c-algo-bit)
 i2c-adap-ibm_ocp: IBM 4xx processor I2C device (uses i2c-algo-ibm_ocp) (NOT BUILT BY DEFAULT)
 i2c-pport:       Primitive parallel port adapter (uses i2c-algo-bit)
-i2c-rpx:         RPX board Motorola 8xx I2C device (uses i2c-algo-8xx) (NOT BUILT BY DEFAULT)
 i2c-velleman:    Velleman K8000 parallel port adapter (uses i2c-algo-bit)
 
index 3d8d36b0ad1262f0a8b4c0fc2fbce21faf07d318..2c170032bf37432790be70fe2e362ba4146c42b1 100644 (file)
@@ -571,7 +571,7 @@ SMBus communication
                                         u8 command, u8 length,
                                         u8 *values);
   extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
-                                           u8 command, u8 *values);
+                                           u8 command, u8 length, u8 *values);
 
 These ones were removed in Linux 2.6.10 because they had no users, but could
 be added back later if needed:
index c04a421f4a7c70290aaf6d6f4eb54af701fd2ae6..75b3680c41eb835e751a242191f2439914166152 100644 (file)
@@ -37,6 +37,7 @@ Offset        Type            Description
 0x1d0  unsigned long   EFI memory descriptor map pointer
 0x1d4  unsigned long   EFI memory descriptor map size
 0x1e0  unsigned long   ALT_MEM_K, alternative mem check, in Kb
+0x1e4  unsigned long   Scratch field for the kernel setup code
 0x1e8  char            number of entries in E820MAP (below)
 0x1e9  unsigned char   number of entries in EDDBUF (below)
 0x1ea  unsigned char   number of entries in EDD_MBR_SIG_BUFFER (below)
index d485256ee1cead1c71b20610c0db3e458cbd10db..773a814d409361767da369070d2d7e5267536c16 100644 (file)
@@ -19,6 +19,7 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <linux/pci.h>
 
 int sum;
 
@@ -34,13 +35,19 @@ int map_mem(char *path, off_t offset, size_t length, int touch)
                return -1;
        }
 
+       if (fnmatch("/proc/bus/pci/*", path, 0) == 0) {
+               rc = ioctl(fd, PCIIOC_MMAP_IS_MEM);
+               if (rc == -1)
+                       perror("PCIIOC_MMAP_IS_MEM ioctl");
+       }
+
        addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
        if (addr == MAP_FAILED)
                return 1;
 
        if (touch) {
                c = (int *) addr;
-               while (c < (int *) (offset + length))
+               while (c < (int *) (addr + length))
                        sum += *c++;
        }
 
@@ -54,7 +61,7 @@ int map_mem(char *path, off_t offset, size_t length, int touch)
        return 0;
 }
 
-int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch)
+int scan_tree(char *path, char *file, off_t offset, size_t length, int touch)
 {
        struct dirent **namelist;
        char *name, *path2;
@@ -93,7 +100,7 @@ int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch)
                } else {
                        r = lstat(path2, &buf);
                        if (r == 0 && S_ISDIR(buf.st_mode)) {
-                               rc = scan_sysfs(path2, file, offset, length, touch);
+                               rc = scan_tree(path2, file, offset, length, touch);
                                if (rc < 0)
                                        return rc;
                        }
@@ -238,10 +245,15 @@ int main()
        else
                fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
 
-       scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
-       scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
-       scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
-       scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
+       scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
+       scan_tree("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
+       scan_tree("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
+       scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
 
        scan_rom("/sys/devices", "rom");
+
+       scan_tree("/proc/bus/pci", "??.?", 0, 0xA0000, 1);
+       scan_tree("/proc/bus/pci", "??.?", 0xA0000, 0x20000, 0);
+       scan_tree("/proc/bus/pci", "??.?", 0xC0000, 0x40000, 1);
+       scan_tree("/proc/bus/pci", "??.?", 0, 1024*1024, 0);
 }
index 9a431a7d0f5d6c61d45687d580137f04878ca4a7..aa3e953f0f7b3f2d29e1b84f95c29ef4d088dded 100644 (file)
@@ -112,6 +112,18 @@ POTENTIAL ATTRIBUTE ALIASING CASES
 
        The /dev/mem mmap constraints apply.
 
+    mmap of /proc/bus/pci/.../??.?
+
+       This is an MMIO mmap of PCI functions, which additionally may or
+       may not be requested as using the WC attribute.
+
+       If WC is requested, and the region in kern_memmap is either WC
+       or UC, and the EFI memory map designates the region as WC, then
+       the WC mapping is allowed.
+
+       Otherwise, the user mapping must use the same attribute as the
+       kernel mapping.
+
     read/write of /dev/mem
 
        This uses copy_from_user(), which implicitly uses a kernel
index 09c184e41cf8746b577540a349bdaeb43143575e..32c2e9da5f3a3dd0f2c522799ffa92575f64a01e 100644 (file)
@@ -433,6 +433,12 @@ tcp_workaround_signed_windows - BOOLEAN
        not receive a window scaling option from them.
        Default: 0
 
+tcp_dma_copybreak - INTEGER
+       Lower limit, in bytes, of the size of socket reads that will be
+       offloaded to a DMA copy engine, if one is present in the system
+       and CONFIG_NET_DMA is enabled.
+       Default: 4096
+
 CIPSOv4 Variables:
 
 cipso_cache_enable - BOOLEAN
index d38261b679053255986f380acdb91e11dabb354a..7754f5aea4e9b0bdd62280fb4f9fe88b23dce3fc 100644 (file)
@@ -113,9 +113,6 @@ initialization with a pointer to a structure describing the driver
                (Please see Documentation/power/pci.txt for descriptions
                of PCI Power Management and the related functions.)
 
-       enable_wake     Enable device to generate wake events from a low power
-                       state.
-
        shutdown        Hook into reboot_notifier_list (kernel/sys.c).
                        Intended to stop any idling DMA operations.
                        Useful for enabling wake-on-lan (NIC) or changing
@@ -299,7 +296,10 @@ If the PCI device can use the PCI Memory-Write-Invalidate transaction,
 call pci_set_mwi().  This enables the PCI_COMMAND bit for Mem-Wr-Inval
 and also ensures that the cache line size register is set correctly.
 Check the return value of pci_set_mwi() as not all architectures
-or chip-sets may support Memory-Write-Invalidate.
+or chip-sets may support Memory-Write-Invalidate.  Alternatively,
+if Mem-Wr-Inval would be nice to have but is not required, call
+pci_try_set_mwi() to have the system do its best effort at enabling
+Mem-Wr-Inval.
 
 
 3.2 Request MMIO/IOP resources
index e00b099a4b8678844edc3f91427f1a184afe8648..dd8fe43888d3e3d6449a1819c84c204a6d197fc6 100644 (file)
@@ -164,7 +164,6 @@ struct pci_driver:
 
         int  (*suspend) (struct pci_dev *dev, pm_message_t state);
         int  (*resume) (struct pci_dev *dev);
-        int  (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable);
 
 
 suspend
@@ -251,42 +250,6 @@ The driver should update the current_state field in its pci_dev structure in
 this function, except for PM-capable devices when pci_set_power_state is used.
 
 
-enable_wake
------------
-
-Usage:
-
-if (dev->driver && dev->driver->enable_wake)
-       dev->driver->enable_wake(dev,state,enable);
-
-This callback is generally only relevant for devices that support the PCI PM
-spec and have the ability to generate a PME# (Power Management Event Signal)
-to wake the system up. (However, it is possible that a device may support 
-some non-standard way of generating a wake event on sleep.)
-
-Bits 15:11 of the PMC (Power Mgmt Capabilities) Register in a device's
-PM Capabilities describe what power states the device supports generating a 
-wake event from:
-
-+------------------+
-|  Bit  |  State   |
-+------------------+
-|  11   |   D0     |
-|  12   |   D1     |
-|  13   |   D2     |
-|  14   |   D3hot  |
-|  15   |   D3cold |
-+------------------+
-
-A device can use this to enable wake events:
-
-        pci_enable_wake(dev,state,enable);
-
-Note that to enable PME# from D3cold, a value of 4 should be passed to 
-pci_enable_wake (since it uses an index into a bitmask). If a driver gets
-a request to enable wake events from D3, two calls should be made to 
-pci_enable_wake (one for both D3hot and D3cold).
-
 
 A reference implementation
 -------------------------
index 5b8d6953f05e741b6b6a3dd88e1ee0c6681f680a..152b510d1bbb5560945e3550c9b0276f7aa452ab 100644 (file)
@@ -393,6 +393,9 @@ safest thing is to unmount all filesystems on removable media (such USB,
 Firewire, CompactFlash, MMC, external SATA, or even IDE hotplug bays)
 before suspending; then remount them after resuming.
 
+There is a work-around for this problem.  For more information, see
+Documentation/usb/persist.txt.
+
 Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were
 compiled with the similar configuration files. Anyway I found that
 suspend to disk (and resume) is much slower on 2.6.16 compared to
index 1d192565e18207188cc93b54d962dd7d5974d7bb..8cfca173d4bca46fab5c121be80d070858aaa0c6 100644 (file)
@@ -31,6 +31,7 @@ Currently, these files are in /proc/sys/vm:
 - min_unmapped_ratio
 - min_slab_ratio
 - panic_on_oom
+- mmap_min_address
 
 ==============================================================
 
@@ -216,3 +217,17 @@ above-mentioned.
 The default value is 0.
 1 and 2 are for failover of clustering. Please select either
 according to your policy of failover.
+
+==============================================================
+
+mmap_min_addr
+
+This file indicates the amount of address space  which a user process will
+be restricted from mmaping.  Since kernel null dereference bugs could
+accidentally operate based on the information in the first couple of pages
+of memory userspace processes should not be allowed to write to them.  By
+default this value is set to 0 and no protections will be enforced by the
+security module.  Setting this value to something like 64k will allow the
+vast majority of applications to work correctly and provide defense in depth
+against future potential kernel bugs.
+
diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt
new file mode 100644 (file)
index 0000000..42861bb
--- /dev/null
@@ -0,0 +1,166 @@
+Rules on how to access information in the Linux kernel sysfs
+
+The kernel exported sysfs exports internal kernel implementation-details
+and depends on internal kernel structures and layout. It is agreed upon
+by the kernel developers that the Linux kernel does not provide a stable
+internal API. As sysfs is a direct export of kernel internal
+structures, the sysfs interface can not provide a stable interface eighter,
+it may always change along with internal kernel changes.
+
+To minimize the risk of breaking users of sysfs, which are in most cases
+low-level userspace applications, with a new kernel release, the users
+of sysfs must follow some rules to use an as abstract-as-possible way to
+access this filesystem. The current udev and HAL programs already
+implement this and users are encouraged to plug, if possible, into the
+abstractions these programs provide instead of accessing sysfs
+directly.
+
+But if you really do want or need to access sysfs directly, please follow
+the following rules and then your programs should work with future
+versions of the sysfs interface.
+
+- Do not use libsysfs
+  It makes assumptions about sysfs which are not true. Its API does not
+  offer any abstraction, it exposes all the kernel driver-core
+  implementation details in its own API. Therefore it is not better than
+  reading directories and opening the files yourself.
+  Also, it is not actively maintained, in the sense of reflecting the
+  current kernel-development. The goal of providing a stable interface
+  to sysfs has failed, it causes more problems, than it solves. It
+  violates many of the rules in this document.
+
+- sysfs is always at /sys
+  Parsing /proc/mounts is a waste of time. Other mount points are a
+  system configuration bug you should not try to solve. For test cases,
+  possibly support a SYSFS_PATH environment variable to overwrite the
+  applications behavior, but never try to search for sysfs. Never try
+  to mount it, if you are not an early boot script.
+
+- devices are only "devices"
+  There is no such thing like class-, bus-, physical devices,
+  interfaces, and such that you can rely on in userspace. Everything is
+  just simply a "device". Class-, bus-, physical, ... types are just
+  kernel implementation details, which should not be expected by
+  applications that look for devices in sysfs.
+
+  The properties of a device are:
+    o devpath (/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0)
+      - identical to the DEVPATH value in the event sent from the kernel
+        at device creation and removal
+      - the unique key to the device at that point in time
+      - the kernels path to the device-directory without the leading
+        /sys, and always starting with with a slash
+      - all elements of a devpath must be real directories. Symlinks
+        pointing to /sys/devices must always be resolved to their real
+        target, and the target path must be used to access the device.
+        That way the devpath to the device matches the devpath of the
+        kernel used at event time.
+      - using or exposing symlink values as elements in a devpath string
+        is a bug in the application
+
+    o kernel name (sda, tty, 0000:00:1f.2, ...)
+      - a directory name, identical to the last element of the devpath
+      - applications need to handle spaces and characters like '!' in
+        the name
+
+    o subsystem (block, tty, pci, ...)
+      - simple string, never a path or a link
+      - retrieved by reading the "subsystem"-link and using only the
+        last element of the target path
+
+    o driver (tg3, ata_piix, uhci_hcd)
+      - a simple string, which may contain spaces, never a path or a
+        link
+      - it is retrieved by reading the "driver"-link and using only the
+        last element of the target path
+      - devices which do not have "driver"-link, just do not have a
+        driver; copying the driver value in a child device context, is a
+        bug in the application
+
+    o attributes
+      - the files in the device directory or files below a subdirectories
+        of the same device directory
+      - accessing attributes reached by a symlink pointing to another device,
+        like the "device"-link, is a bug in the application
+
+  Everything else is just a kernel driver-core implementation detail,
+  that should not be assumed to be stable across kernel releases.
+
+- Properties of parent devices never belong into a child device.
+  Always look at the parent devices themselves for determining device
+  context properties. If the device 'eth0' or 'sda' does not have a
+  "driver"-link, then this device does not have a driver. Its value is empty.
+  Never copy any property of the parent-device into a child-device. Parent
+  device-properties may change dynamically without any notice to the
+  child device.
+
+- Hierarchy in a single device-tree
+  There is only one valid place in sysfs where hierarchy can be examined
+  and this is below: /sys/devices.
+  It is planned, that all device directories will end up in the tree
+  below this directory.
+
+- Classification by subsystem
+  There are currently three places for classification of devices:
+  /sys/block, /sys/class and /sys/bus. It is planned that these will
+  not contain any device-directories themselves, but only flat lists of
+  symlinks pointing to the unified /sys/devices tree.
+  All three places have completely different rules on how to access
+  device information. It is planned to merge all three
+  classification-directories into one place at /sys/subsystem,
+  following the layout of the bus-directories. All buses and
+  classes, including the converted block-subsystem, will show up
+  there.
+  The devices belonging to a subsystem will create a symlink in the
+  "devices" directory at /sys/subsystem/<name>/devices.
+
+  If /sys/subsystem exists, /sys/bus, /sys/class and /sys/block can be
+  ignored. If it does not exist, you have always to scan all three
+  places, as the kernel is free to move a subsystem from one place to
+  the other, as long as the devices are still reachable by the same
+  subsystem name.
+
+  Assuming /sys/class/<subsystem> and /sys/bus/<subsystem>, or
+  /sys/block and /sys/class/block are not interchangeable, is a bug in
+  the application.
+
+- Block
+  The converted block-subsystem at /sys/class/block, or
+  /sys/subsystem/block will contain the links for disks and partitions
+  at the same level, never in a hierarchy. Assuming the block-subsytem to
+  contain only disks and not partition-devices in the same flat list is
+  a bug in the application.
+
+- "device"-link and <subsystem>:<kernel name>-links
+  Never depend on the "device"-link. The "device"-link is a workaround
+  for the old layout, where class-devices are not created in
+  /sys/devices/ like the bus-devices. If the link-resolving of a
+  device-directory does not end in /sys/devices/, you can use the
+  "device"-link to find the parent devices in /sys/devices/. That is the
+  single valid use of the "device"-link, it must never appear in any
+  path as an element. Assuming the existence of the "device"-link for
+  a device in /sys/devices/ is a bug in the application.
+  Accessing /sys/class/net/eth0/device is a bug in the application.
+
+  Never depend on the class-specific links back to the /sys/class
+  directory.  These links are also a workaround for the design mistake
+  that class-devices are not created in /sys/devices. If a device
+  directory does not contain directories for child devices, these links
+  may be used to find the child devices in /sys/class. That is the single
+  valid use of these links, they must never appear in any path as an
+  element. Assuming the existence of these links for devices which are
+  real child device directories in the /sys/devices tree, is a bug in
+  the application.
+
+  It is planned to remove all these links when when all class-device
+  directories live in /sys/devices.
+
+- Position of devices along device chain can change.
+  Never depend on a specific parent device position in the devpath,
+  or the chain of parent devices. The kernel is free to insert devices into
+  the chain. You must always request the parent device you are looking for
+  by its subsystem value. You need to walk up the chain until you find
+  the device that matches the expected subsystem. Depending on a specific
+  position of a parent device, or exposing relative paths, using "../" to
+  access the chain of parents, is a bug in the application.
+
index 62844aeba69cb4a5c37604f06d7e9de7a04d769d..e8b50b7de9d943d3efd3da6e55ebc12ce533f230 100644 (file)
@@ -32,12 +32,15 @@ ELIMINATING COPIES
 It's good to avoid making CPUs copy data needlessly.  The costs can add up,
 and effects like cache-trashing can impose subtle penalties.
 
-- When you're allocating a buffer for DMA purposes anyway, use the buffer
-  primitives.  Think of them as kmalloc and kfree that give you the right
-  kind of addresses to store in urb->transfer_buffer and urb->transfer_dma,
-  while guaranteeing that no hidden copies through DMA "bounce" buffers will
-  slow things down.  You'd also set URB_NO_TRANSFER_DMA_MAP in
-  urb->transfer_flags:
+- If you're doing lots of small data transfers from the same buffer all
+  the time, that can really burn up resources on systems which use an
+  IOMMU to manage the DMA mappings.  It can cost MUCH more to set up and
+  tear down the IOMMU mappings with each request than perform the I/O!
+
+  For those specific cases, USB has primitives to allocate less expensive
+  memory.  They work like kmalloc and kfree versions that give you the right
+  kind of addresses to store in urb->transfer_buffer and urb->transfer_dma.
+  You'd also set URB_NO_TRANSFER_DMA_MAP in urb->transfer_flags:
 
        void *usb_buffer_alloc (struct usb_device *dev, size_t size,
                int mem_flags, dma_addr_t *dma);
@@ -45,6 +48,10 @@ and effects like cache-trashing can impose subtle penalties.
        void usb_buffer_free (struct usb_device *dev, size_t size,
                void *addr, dma_addr_t dma);
 
+  Most drivers should *NOT* be using these primitives; they don't need
+  to use this type of memory ("dma-coherent"), and memory returned from
+  kmalloc() will work just fine.
+
   For control transfers you can use the buffer primitives or not for each
   of the transfer buffer and setup buffer independently.  Set the flag bits
   URB_NO_TRANSFER_DMA_MAP and URB_NO_SETUP_DMA_MAP to indicate which
@@ -54,29 +61,39 @@ and effects like cache-trashing can impose subtle penalties.
   The memory buffer returned is "dma-coherent"; sometimes you might need to
   force a consistent memory access ordering by using memory barriers.  It's
   not using a streaming DMA mapping, so it's good for small transfers on
-  systems where the I/O would otherwise tie up an IOMMU mapping.  (See
+  systems where the I/O would otherwise thrash an IOMMU mapping.  (See
   Documentation/DMA-mapping.txt for definitions of "coherent" and "streaming"
   DMA mappings.)
 
   Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
   space-efficient.
 
+  On most systems the memory returned will be uncached, because the
+  semantics of dma-coherent memory require either bypassing CPU caches
+  or using cache hardware with bus-snooping support.  While x86 hardware
+  has such bus-snooping, many other systems use software to flush cache
+  lines to prevent DMA conflicts.
+
 - Devices on some EHCI controllers could handle DMA to/from high memory.
-  Driver probe() routines can notice this using a generic DMA call, then
-  tell higher level code (network, scsi, etc) about it like this:
 
-       if (dma_supported (&intf->dev, 0xffffffffffffffffULL))
-               net->features |= NETIF_F_HIGHDMA;
+  Unfortunately, the current Linux DMA infrastructure doesn't have a sane
+  way to expose these capabilities ... and in any case, HIGHMEM is mostly a
+  design wart specific to x86_32.  So your best bet is to ensure you never
+  pass a highmem buffer into a USB driver.  That's easy; it's the default
+  behavior.  Just don't override it; e.g. with NETIF_F_HIGHDMA.
 
-  That can eliminate dma bounce buffering of requests that originate (or
-  terminate) in high memory, in cases where the buffers aren't allocated
-  with usb_buffer_alloc() but instead are dma-mapped.
+  This may force your callers to do some bounce buffering, copying from
+  high memory to "normal" DMA memory.  If you can come up with a good way
+  to fix this issue (for x86_32 machines with over 1 GByte of memory),
+  feel free to submit patches.
 
 
 WORKING WITH EXISTING BUFFERS
 
 Existing buffers aren't usable for DMA without first being mapped into the
-DMA address space of the device.
+DMA address space of the device.  However, most buffers passed to your
+driver can safely be used with such DMA mapping.  (See the first section
+of DMA-mapping.txt, titled "What memory is DMA-able?")
 
 - When you're using scatterlists, you can map everything at once.  On some
   systems, this kicks in an IOMMU and turns the scatterlists into single
@@ -114,3 +131,8 @@ DMA address space of the device.
   The calls manage urb->transfer_dma for you, and set URB_NO_TRANSFER_DMA_MAP
   so that usbcore won't map or unmap the buffer.  The same goes for
   urb->setup_dma and URB_NO_SETUP_DMA_MAP for control requests.
+
+Note that several of those interfaces are currently commented out, since
+they don't have current users.  See the source code.  Other than the dmasync
+calls (where the underlying DMA primitives have changed), most of them can
+easily be commented back in if you want to use them.
diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
new file mode 100644 (file)
index 0000000..df54d64
--- /dev/null
@@ -0,0 +1,156 @@
+               USB device persistence during system suspend
+
+                  Alan Stern <stern@rowland.harvard.edu>
+
+                September 2, 2006 (Updated May 29, 2007)
+
+
+       What is the problem?
+
+According to the USB specification, when a USB bus is suspended the
+bus must continue to supply suspend current (around 1-5 mA).  This
+is so that devices can maintain their internal state and hubs can
+detect connect-change events (devices being plugged in or unplugged).
+The technical term is "power session".
+
+If a USB device's power session is interrupted then the system is
+required to behave as though the device has been unplugged.  It's a
+conservative approach; in the absence of suspend current the computer
+has no way to know what has actually happened.  Perhaps the same
+device is still attached or perhaps it was removed and a different
+device plugged into the port.  The system must assume the worst.
+
+By default, Linux behaves according to the spec.  If a USB host
+controller loses power during a system suspend, then when the system
+wakes up all the devices attached to that controller are treated as
+though they had disconnected.  This is always safe and it is the
+"officially correct" thing to do.
+
+For many sorts of devices this behavior doesn't matter in the least.
+If the kernel wants to believe that your USB keyboard was unplugged
+while the system was asleep and a new keyboard was plugged in when the
+system woke up, who cares?  It'll still work the same when you type on
+it.
+
+Unfortunately problems _can_ arise, particularly with mass-storage
+devices.  The effect is exactly the same as if the device really had
+been unplugged while the system was suspended.  If you had a mounted
+filesystem on the device, you're out of luck -- everything in that
+filesystem is now inaccessible.  This is especially annoying if your
+root filesystem was located on the device, since your system will
+instantly crash.
+
+Loss of power isn't the only mechanism to worry about.  Anything that
+interrupts a power session will have the same effect.  For example,
+even though suspend current may have been maintained while the system
+was asleep, on many systems during the initial stages of wakeup the
+firmware (i.e., the BIOS) resets the motherboard's USB host
+controllers.  Result: all the power sessions are destroyed and again
+it's as though you had unplugged all the USB devices.  Yes, it's
+entirely the BIOS's fault, but that doesn't do _you_ any good unless
+you can convince the BIOS supplier to fix the problem (lots of luck!).
+
+On many systems the USB host controllers will get reset after a
+suspend-to-RAM.  On almost all systems, no suspend current is
+available during hibernation (also known as swsusp or suspend-to-disk).
+You can check the kernel log after resuming to see if either of these
+has happened; look for lines saying "root hub lost power or was reset".
+
+In practice, people are forced to unmount any filesystems on a USB
+device before suspending.  If the root filesystem is on a USB device,
+the system can't be suspended at all.  (All right, it _can_ be
+suspended -- but it will crash as soon as it wakes up, which isn't
+much better.)
+
+
+       What is the solution?
+
+Setting CONFIG_USB_PERSIST will cause the kernel to work around these
+issues.  It enables a mode in which the core USB device data
+structures are allowed to persist across a power-session disruption.
+It works like this.  If the kernel sees that a USB host controller is
+not in the expected state during resume (i.e., if the controller was
+reset or otherwise had lost power) then it applies a persistence check
+to each of the USB devices below that controller for which the
+"persist" attribute is set.  It doesn't try to resume the device; that
+can't work once the power session is gone.  Instead it issues a USB
+port reset and then re-enumerates the device.  (This is exactly the
+same thing that happens whenever a USB device is reset.)  If the
+re-enumeration shows that the device now attached to that port has the
+same descriptors as before, including the Vendor and Product IDs, then
+the kernel continues to use the same device structure.  In effect, the
+kernel treats the device as though it had merely been reset instead of
+unplugged.
+
+If no device is now attached to the port, or if the descriptors are
+different from what the kernel remembers, then the treatment is what
+you would expect.  The kernel destroys the old device structure and
+behaves as though the old device had been unplugged and a new device
+plugged in, just as it would without the CONFIG_USB_PERSIST option.
+
+The end result is that the USB device remains available and usable.
+Filesystem mounts and memory mappings are unaffected, and the world is
+now a good and happy place.
+
+Note that even when CONFIG_USB_PERSIST is set, the "persist" feature
+will be applied only to those devices for which it is enabled.  You
+can enable the feature by doing (as root):
+
+       echo 1 >/sys/bus/usb/devices/.../power/persist
+
+where the "..." should be filled in the with the device's ID.  Disable
+the feature by writing 0 instead of 1.  For hubs the feature is
+automatically and permanently enabled, so you only have to worry about
+setting it for devices where it really matters.
+
+
+       Is this the best solution?
+
+Perhaps not.  Arguably, keeping track of mounted filesystems and
+memory mappings across device disconnects should be handled by a
+centralized Logical Volume Manager.  Such a solution would allow you
+to plug in a USB flash device, create a persistent volume associated
+with it, unplug the flash device, plug it back in later, and still
+have the same persistent volume associated with the device.  As such
+it would be more far-reaching than CONFIG_USB_PERSIST.
+
+On the other hand, writing a persistent volume manager would be a big
+job and using it would require significant input from the user.  This
+solution is much quicker and easier -- and it exists now, a giant
+point in its favor!
+
+Furthermore, the USB_PERSIST option applies to _all_ USB devices, not
+just mass-storage devices.  It might turn out to be equally useful for
+other device types, such as network interfaces.
+
+
+       WARNING: Using CONFIG_USB_PERSIST can be dangerous!!
+
+When recovering an interrupted power session the kernel does its best
+to make sure the USB device hasn't been changed; that is, the same
+device is still plugged into the port as before.  But the checks
+aren't guaranteed to be 100% accurate.
+
+If you replace one USB device with another of the same type (same
+manufacturer, same IDs, and so on) there's an excellent chance the
+kernel won't detect the change.  Serial numbers and other strings are
+not compared.  In many cases it wouldn't help if they were, because
+manufacturers frequently omit serial numbers entirely in their
+devices.
+
+Furthermore it's quite possible to leave a USB device exactly the same
+while changing its media.  If you replace the flash memory card in a
+USB card reader while the system is asleep, the kernel will have no
+way to know you did it.  The kernel will assume that nothing has
+happened and will continue to use the partition tables, inodes, and
+memory mappings for the old card.
+
+If the kernel gets fooled in this way, it's almost certain to cause
+data corruption and to crash your system.  You'll have no one to blame
+but yourself.
+
+YOU HAVE BEEN WARNED!  USE AT YOUR OWN RISK!
+
+That having been said, most of the time there shouldn't be any trouble
+at all.  The "persist" feature can be extremely useful.  Make the most
+of it.
index fcfe598b8d743f4a4c773089409386fcf39826de..360eb581953b658ae9ba6947b95c081866f5fd78 100644 (file)
@@ -315,10 +315,9 @@ M: zippel@linux-m68k.org
 S:     Maintained
 
 AGPGART DRIVER
-P:     Dave Jones
-M:     davej@codemonkey.org.uk
-W:     http://www.codemonkey.org.uk/projects/agp/
-T:     git kernel.org:/pub/scm/linux/kernel/git/davej/agpgart.git
+P:     David Airlie
+M:     airlied@linux.ie
+T:     git kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
 S:     Maintained
 
 AHA152X SCSI DRIVER
@@ -371,7 +370,7 @@ P:  Tom Tucker
 M:     tom@opengridcomputing.com
 P:     Steve Wise
 M:     swise@opengridcomputing.com
-L:     openib-general@openib.org
+L:     general@lists.openfabrics.org
 S:     Maintained
 
 AOA (Apple Onboard Audio) ALSA DRIVER
@@ -1396,7 +1395,7 @@ P:        Hoang-Nam Nguyen
 M:     hnguyen@de.ibm.com
 P:     Christoph Raisch
 M:     raisch@de.ibm.com
-L:     openib-general@openib.org
+L:     general@lists.openfabrics.org
 S:     Supported
 
 EMU10K1 SOUND DRIVER
@@ -1750,8 +1749,8 @@ T:        http://www.harbaum.org/till/i2c_tiny_usb
 S:     Maintained
 
 i386 BOOT CODE
-P:     Riley H. Williams
-M:     Riley@Williams.Name
+P:     H. Peter Anvin
+M:     hpa@zytor.com
 L:     Linux-Kernel@vger.kernel.org
 S:     Maintained
 
@@ -1850,8 +1849,8 @@ M:        rolandd@cisco.com
 P:     Sean Hefty
 M:     mshefty@ichips.intel.com
 P:     Hal Rosenstock
-M:     halr@voltaire.com
-L:     openib-general@openib.org
+M:     hal.rosenstock@gmail.com 
+L:     general@lists.openfabrics.org
 W:     http://www.openib.org/
 T:     git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
 S:     Supported
@@ -1989,9 +1988,10 @@ M:       jjciarla@raiz.uncu.edu.ar
 S:     Maintained
 
 IPATH DRIVER:
-P:     Bryan O'Sullivan
-M:     support@pathscale.com
-L:     openib-general@openib.org
+P:     Arthur Jones
+M:     infinipath@qlogic.com
+L:     general@lists.openfabrics.org
+T:     git git://git.qlogic.com/ipath-linux-2.6
 S:     Supported
 
 IPMI SUBSYSTEM
@@ -2330,6 +2330,12 @@ W:       http://linuxwireless.org/
 T:     git kernel.org:/pub/scm/linux/kernel/git/jbenc/mac80211.git
 S:     Maintained
 
+MACVLAN DRIVER
+P:     Patrick McHardy
+M:     kaber@trash.net
+L:     netdev@vger.kernel.org
+S:     Maintained
+
 MARVELL YUKON / SYSKONNECT DRIVER
 P:     Mirko Lindner
 M:     mlindner@syskonnect.de
@@ -2814,11 +2820,6 @@ P:       Kristen Carlson Accardi
 M:     kristen.c.accardi@intel.com
 S:     Supported
 
-PCI HOTPLUG COMPAQ DRIVER
-P:     Greg Kroah-Hartman
-M:     greg@kroah.com
-S:     Maintained
-
 PCIE HOTPLUG DRIVER
 P:     Kristen Carlson Accardi
 M:     kristen.c.accardi@intel.com
@@ -3729,12 +3730,12 @@ L:      netdev@vger.kernel.org
 W:     http://pegasus2.sourceforge.net/
 S:     Maintained
 
-USB PRINTER DRIVER
-P:     Vojtech Pavlik
-M:     vojtech@suse.cz
+USB PRINTER DRIVER (usblp)
+P:     Pete Zaitcev
+M:     zaitcev@redhat.com
 L:     linux-usb-users@lists.sourceforge.net
 L:     linux-usb-devel@lists.sourceforge.net
-S:     Maintained
+S:     Supported
 
 USB RTL8150 DRIVER
 P:     Petko Manolov
index 79c6e5a2445652679b4aafa5d647e06248fe27b2..2a85dc33907c2c66f09c3e3ce61e96ef19e23d3a 100644 (file)
@@ -327,6 +327,9 @@ config PCI_DOMAINS
        bool
        default y
 
+config PCI_SYSCALL
+       def_bool PCI
+
 config ALPHA_CORE_AGP
        bool
        depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL
index 28c84e55feb9b80440deda421730ff0c126e2963..6b07f89a72c70af2b4bf11d7ab5eb3653db0102c 100644 (file)
@@ -207,6 +207,10 @@ iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n)
                p[i] = 0;
 }
 \f
+/* True if the machine supports DAC addressing, and DEV can
+   make use of it given MASK.  */
+static int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask);
+
 /* Map a single buffer of the indicated size for PCI DMA in streaming
    mode.  The 32-bit PCI bus mastering address to use is returned.
    Once the device is given the dma address, the device owns this memory
@@ -897,7 +901,7 @@ iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count)
 /* True if the machine supports DAC addressing, and DEV can
    make use of it given MASK.  */
 
-int
+static int
 pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
 {
        dma64_addr_t dac_offset = alpha_mv.pci_dac_offset;
@@ -917,32 +921,6 @@ pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
 
        return ok;
 }
-EXPORT_SYMBOL(pci_dac_dma_supported);
-
-dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page,
-                   unsigned long offset, int direction)
-{
-       return (alpha_mv.pci_dac_offset
-               + __pa(page_address(page)) 
-               + (dma64_addr_t) offset);
-}
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-       unsigned long paddr = (dma_addr & PAGE_MASK) - alpha_mv.pci_dac_offset;
-       return virt_to_page(__va(paddr));
-}
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-       return (dma_addr & ~PAGE_MASK);
-}
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
 
 /* Helper for generic DMA-mapping functions. */
 
index 50d9f3e4e0f1ad315eb9a04e1e3e9aa5299d6fa5..a44c6da9bf8363d21169eecb1521ef8f16144e7a 100644 (file)
@@ -241,6 +241,9 @@ config ARCH_H720X
 
 config ARCH_IMX
        bool "IMX"
+       select GENERIC_GPIO
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
        help
          Support for Motorola's i.MX family of processors (MX1, MXL).
 
@@ -308,6 +311,7 @@ config ARCH_L7200
 
 config ARCH_KS8695
        bool "Micrel/Kendin KS8695"
+       select GENERIC_GPIO
        help
          Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
          System-on-Chip devices.
@@ -384,6 +388,7 @@ config ARCH_DAVINCI
        bool "TI DaVinci"
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
+       select GENERIC_GPIO
        help
          Support for TI's DaVinci platform.
 
@@ -531,6 +536,9 @@ config PCI
          information about which PCI hardware does work under Linux and which
          doesn't.
 
+config PCI_SYSCALL
+       def_bool PCI
+
 # Select the host bridge type
 config PCI_HOST_VIA82C505
        bool
@@ -1034,6 +1042,8 @@ source "drivers/mmc/Kconfig"
 
 source "drivers/rtc/Kconfig"
 
+source "drivers/dma/Kconfig"
+
 endmenu
 
 source "fs/Kconfig"
index aefee20cbf987abc7db39f5dc7084b0bed127b47..b15f927a5926187f90f0ba50da935c18a4a5061e 100644 (file)
@@ -1 +1,2 @@
 piggy.gz
+font.c
index adddc71316852f5001314faf10678f5fc4e3ef8d..a1f1691b67fe212f01c11a5e20f0f5fc78087fd3 100644 (file)
@@ -6,15 +6,13 @@
 
 HEAD   = head.o
 OBJS   = misc.o
-FONTC  = drivers/video/console/font_acorn_8x8.c
-
-FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o)
+FONTC  = $(srctree)/drivers/video/console/font_acorn_8x8.c
 
 #
 # Architecture dependencies
 #
 ifeq ($(CONFIG_ARCH_ACORN),y)
-OBJS           += ll_char_wr.o $(FONT)
+OBJS           += ll_char_wr.o font.o
 endif
 
 ifeq ($(CONFIG_ARCH_SHARK),y)
@@ -73,7 +71,7 @@ endif
 
 SEDFLAGS       = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
 
-targets       := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \
+targets       := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
                 head.o misc.o $(OBJS)
 EXTRA_CFLAGS  := -fpic
 EXTRA_AFLAGS  :=
@@ -105,7 +103,10 @@ $(obj)/piggy.gz: $(obj)/../Image FORCE
 
 $(obj)/piggy.o:  $(obj)/piggy.gz FORCE
 
-CFLAGS_font_acorn_8x8.o := -Dstatic=
+CFLAGS_font.o := -Dstatic=
+
+$(obj)/font.c: $(FONTC)
+       $(call cmd,shipped)
 
 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
        @sed "$(SEDFLAGS)" < $< > $@
index 73c5d9e0201c47fd48b6a79194e3cb0413d5147f..236bbe5783123ceaaa3284bd7b1920007fb9f084 100644 (file)
@@ -41,11 +41,6 @@ __XScale_start:
                mov     r7, #MACH_TYPE_COTULLA_IDP
 #endif
 
-#ifdef  CONFIG_MACH_GTWX5715
-               mov     r7, #(MACH_TYPE_GTWX5715 & 0xff)
-               orr     r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00)
-#endif
-
 #ifdef CONFIG_ARCH_IXP2000
                mov     r1, #-1
                mov     r0, #0xd6000000
index 680ea6ed77b89c746715f0a38c42142f52a0b4b3..d7fb5ee1637e8f25e23edcd69b7acbeca019b539 100644 (file)
@@ -436,6 +436,28 @@ __armv4_mmu_cache_on:
                mcr     p15, 0, r0, c8, c7, 0   @ flush I,D TLBs
                mov     pc, r12
 
+__armv7_mmu_cache_on:
+               mov     r12, lr
+               mrc     p15, 0, r11, c0, c1, 4  @ read ID_MMFR0
+               tst     r11, #0xf               @ VMSA
+               blne    __setup_mmu
+               mov     r0, #0
+               mcr     p15, 0, r0, c7, c10, 4  @ drain write buffer
+               tst     r11, #0xf               @ VMSA
+               mcrne   p15, 0, r0, c8, c7, 0   @ flush I,D TLBs
+               mrc     p15, 0, r0, c1, c0, 0   @ read control reg
+               orr     r0, r0, #0x5000         @ I-cache enable, RR cache replacement
+               orr     r0, r0, #0x003c         @ write buffer
+               orrne   r0, r0, #1              @ MMU enabled
+               movne   r1, #-1
+               mcrne   p15, 0, r3, c2, c0, 0   @ load page table pointer
+               mcrne   p15, 0, r1, c3, c0, 0   @ load domain access control
+               mcr     p15, 0, r0, c1, c0, 0   @ load control register
+               mrc     p15, 0, r0, c1, c0, 0   @ and read it back
+               mov     r0, #0
+               mcr     p15, 0, r0, c7, c5, 4   @ ISB
+               mov     pc, r12
+
 __arm6_mmu_cache_on:
                mov     r12, lr
                bl      __setup_mmu
@@ -622,11 +644,17 @@ proc_types:
                b       __armv4_mmu_cache_flush
 
                .word   0x0007b000              @ ARMv6
-               .word   0x0007f000
+               .word   0x000ff000
                b       __armv4_mmu_cache_on
                b       __armv4_mmu_cache_off
                b       __armv6_mmu_cache_flush
 
+               .word   0x000f0000              @ new CPU Id
+               .word   0x000f0000
+               b       __armv7_mmu_cache_on
+               b       __armv7_mmu_cache_off
+               b       __armv7_mmu_cache_flush
+
                .word   0                       @ unrecognised type
                .word   0
                mov     pc, lr
@@ -674,6 +702,16 @@ __armv4_mmu_cache_off:
                mcr     p15, 0, r0, c8, c7      @ invalidate whole TLB v4
                mov     pc, lr
 
+__armv7_mmu_cache_off:
+               mrc     p15, 0, r0, c1, c0
+               bic     r0, r0, #0x000d
+               mcr     p15, 0, r0, c1, c0      @ turn MMU and cache off
+               mov     r12, lr
+               bl      __armv7_mmu_cache_flush
+               mov     r0, #0
+               mcr     p15, 0, r0, c8, c7, 0   @ invalidate whole TLB
+               mov     pc, r12
+
 __arm6_mmu_cache_off:
                mov     r0, #0x00000030         @ ARM6 control reg.
                b       __armv3_mmu_cache_off
@@ -730,6 +768,59 @@ __armv6_mmu_cache_flush:
                mcr     p15, 0, r1, c7, c10, 4  @ drain WB
                mov     pc, lr
 
+__armv7_mmu_cache_flush:
+               mrc     p15, 0, r10, c0, c1, 5  @ read ID_MMFR1
+               tst     r10, #0xf << 16         @ hierarchical cache (ARMv7)
+               beq     hierarchical
+               mov     r10, #0
+               mcr     p15, 0, r10, c7, c14, 0 @ clean+invalidate D
+               b       iflush
+hierarchical:
+               stmfd   sp!, {r0-r5, r7, r9-r11}
+               mrc     p15, 1, r0, c0, c0, 1   @ read clidr
+               ands    r3, r0, #0x7000000      @ extract loc from clidr
+               mov     r3, r3, lsr #23         @ left align loc bit field
+               beq     finished                @ if loc is 0, then no need to clean
+               mov     r10, #0                 @ start clean at cache level 0
+loop1:
+               add     r2, r10, r10, lsr #1    @ work out 3x current cache level
+               mov     r1, r0, lsr r2          @ extract cache type bits from clidr
+               and     r1, r1, #7              @ mask of the bits for current cache only
+               cmp     r1, #2                  @ see what cache we have at this level
+               blt     skip                    @ skip if no cache, or just i-cache
+               mcr     p15, 2, r10, c0, c0, 0  @ select current cache level in cssr
+               mcr     p15, 0, r10, c7, c5, 4  @ isb to sych the new cssr&csidr
+               mrc     p15, 1, r1, c0, c0, 0   @ read the new csidr
+               and     r2, r1, #7              @ extract the length of the cache lines
+               add     r2, r2, #4              @ add 4 (line length offset)
+               ldr     r4, =0x3ff
+               ands    r4, r4, r1, lsr #3      @ find maximum number on the way size
+               .word   0xe16f5f14              @ clz r5, r4 - find bit position of way size increment
+               ldr     r7, =0x7fff
+               ands    r7, r7, r1, lsr #13     @ extract max number of the index size
+loop2:
+               mov     r9, r4                  @ create working copy of max way size
+loop3:
+               orr     r11, r10, r9, lsl r5    @ factor way and cache number into r11
+               orr     r11, r11, r7, lsl r2    @ factor index number into r11
+               mcr     p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
+               subs    r9, r9, #1              @ decrement the way
+               bge     loop3
+               subs    r7, r7, #1              @ decrement the index
+               bge     loop2
+skip:
+               add     r10, r10, #2            @ increment cache number
+               cmp     r3, r10
+               bgt     loop1
+finished:
+               mov     r10, #0                 @ swith back to cache level 0
+               mcr     p15, 2, r10, c0, c0, 0  @ select current cache level in cssr
+               ldmfd   sp!, {r0-r5, r7, r9-r11}
+iflush:
+               mcr     p15, 0, r10, c7, c5, 0  @ invalidate I+BTB
+               mcr     p15, 0, r10, c7, c10, 4 @ drain WB
+               mov     pc, lr
+
 __armv4_mmu_cache_flush:
                mov     r2, #64*1024            @ default: 32K dcache size (*2)
                mov     r11, #32                @ default: 32 byte line size
index cfe6f4650bc9fffc836136ecc9ee61d7b5ca0a9c..ae21755872ed2c8e8d6ad4bdaef3207d1fcb09f9 100644 (file)
@@ -60,6 +60,9 @@ struct locomo {
        unsigned int irq;
        spinlock_t lock;
        void __iomem *base;
+#ifdef CONFIG_PM
+       void *saved_state;
+#endif
 };
 
 struct locomo_dev_info {
@@ -565,7 +568,7 @@ static int locomo_suspend(struct platform_device *dev, pm_message_t state)
        if (!save)
                return -ENOMEM;
 
-       dev->dev.power.saved_state = (void *) save;
+       lchip->saved_state = save;
 
        spin_lock_irqsave(&lchip->lock, flags);
 
@@ -605,8 +608,8 @@ static int locomo_resume(struct platform_device *dev)
        struct locomo_save_data *save;
        unsigned long r;
        unsigned long flags;
-       
-       save = (struct locomo_save_data *) dev->dev.power.saved_state;
+
+       save = lchip->saved_state;
        if (!save)
                return 0;
 
@@ -628,6 +631,8 @@ static int locomo_resume(struct platform_device *dev)
        locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD);
 
        spin_unlock_irqrestore(&lchip->lock, flags);
+
+       lchip->saved_state = NULL;
        kfree(save);
 
        return 0;
index 798bbfccafb74d8d0a6be4b8b5c453add992c7ce..eb06d0b2cb747344c47fb1395d6f2b6fecf080d9 100644 (file)
@@ -51,6 +51,9 @@ struct sa1111 {
        int             irq;
        spinlock_t      lock;
        void __iomem    *base;
+#ifdef CONFIG_PM
+       void            *saved_state;
+#endif
 };
 
 /*
@@ -822,7 +825,7 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
        save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
        if (!save)
                return -ENOMEM;
-       dev->dev.power.saved_state = save;
+       sachip->saved_state = save;
 
        spin_lock_irqsave(&sachip->lock, flags);
 
@@ -878,7 +881,7 @@ static int sa1111_resume(struct platform_device *dev)
        unsigned long flags, id;
        void __iomem *base;
 
-       save = (struct sa1111_save_data *)dev->dev.power.saved_state;
+       save = sachip->saved_state;
        if (!save)
                return 0;
 
@@ -923,7 +926,7 @@ static int sa1111_resume(struct platform_device *dev)
 
        spin_unlock_irqrestore(&sachip->lock, flags);
 
-       dev->dev.power.saved_state = NULL;
+       sachip->saved_state = NULL;
        kfree(save);
 
        return 0;
@@ -958,8 +961,8 @@ static int sa1111_remove(struct platform_device *pdev)
                platform_set_drvdata(pdev, NULL);
 
 #ifdef CONFIG_PM
-               kfree(pdev->dev.power.saved_state);
-               pdev->dev.power.saved_state = NULL;
+               kfree(sachip->saved_state);
+               sachip->saved_state = NULL;
 #endif
        }
 
index 3bf3a927ae22fbb4d09586ce0d55f88bb5f5dcd9..111a7fa5debee4ace5a39f1aa5c50b2ab3927683 100644 (file)
@@ -766,9 +766,7 @@ static void sharpsl_apm_get_power_status(struct apm_power_info *info)
 }
 
 static struct pm_ops sharpsl_pm_ops = {
-       .prepare        = pxa_pm_prepare,
        .enter          = corgi_pxa_pm_enter,
-       .finish         = pxa_pm_finish,
        .valid          = pm_valid_only_mem,
 };
 
index a52da0ddb43d01b26821c4e6c98f59bbe92d4f84..024a9cf469b47d6e841da0147e3c02355268ca81 100644 (file)
@@ -20,7 +20,8 @@ __switch_data:
        .long   _end                            @ r7
        .long   processor_id                    @ r4
        .long   __machine_arch_type             @ r5
-       .long   cr_alignment                    @ r6
+       .long   __atags_pointer                 @ r6
+       .long   cr_alignment                    @ r7
        .long   init_thread_union + THREAD_START_SP @ sp
 
 /*
@@ -29,6 +30,7 @@ __switch_data:
  *
  *  r0  = cp#15 control register
  *  r1  = machine ID
+ *  r2  = atags pointer
  *  r9  = processor ID
  */
        .type   __mmap_switched, %function
@@ -47,11 +49,12 @@ __mmap_switched:
        strcc   fp, [r6],#4
        bcc     1b
 
-       ldmia   r3, {r4, r5, r6, sp}
+       ldmia   r3, {r4, r5, r6, r7, sp}
        str     r9, [r4]                        @ Save processor ID
        str     r1, [r5]                        @ Save machine type
+       str     r2, [r6]                        @ Save atags pointer
        bic     r4, r0, #CR_A                   @ Clear 'A' bit
-       stmia   r6, {r0, r4}                    @ Save control register values
+       stmia   r7, {r0, r4}                    @ Save control register values
        b       start_kernel
 
 /*
@@ -215,3 +218,34 @@ ENTRY(lookup_machine_type)
        bl      __lookup_machine_type
        mov     r0, r5
        ldmfd   sp!, {r4 - r6, pc}
+
+/* Determine validity of the r2 atags pointer.  The heuristic requires
+ * that the pointer be aligned, in the first 16k of physical RAM and
+ * that the ATAG_CORE marker is first and present.  Future revisions
+ * of this function may be more lenient with the physical address and
+ * may also be able to move the ATAGS block if necessary.
+ *
+ * r8  = machinfo
+ *
+ * Returns:
+ *  r2 either valid atags pointer, or zero
+ *  r5, r6 corrupted
+ */
+
+       .type   __vet_atags, %function
+__vet_atags:
+       tst     r2, #0x3                        @ aligned?
+       bne     1f
+
+       ldr     r5, [r2, #0]                    @ is first tag ATAG_CORE?
+       subs    r5, r5, #ATAG_CORE_SIZE
+       bne     1f
+       ldr     r5, [r2, #4]
+       ldr     r6, =ATAG_CORE
+       cmp     r5, r6
+       bne     1f
+
+       mov     pc, lr                          @ atag pointer is ok
+
+1:     mov     r2, #0
+       mov     pc, lr
index 41f98b4ba2ee256d5998a514dd20bcf250bad577..7898cbc9861a9d484d655079c66b3f1e76dccd0b 100644 (file)
 #define KERNEL_RAM_VADDR       (PAGE_OFFSET + TEXT_OFFSET)
 #define KERNEL_RAM_PADDR       (PHYS_OFFSET + TEXT_OFFSET)
 
+#define ATAG_CORE 0x54410001
+#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
+
+
 /*
  * swapper_pg_dir is the virtual address of the initial page table.
  * We place the page tables 16K below KERNEL_RAM_VADDR.  Therefore, we must
@@ -61,7 +65,7 @@
  *
  * This is normally called from the decompressor code.  The requirements
  * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
- * r1 = machine nr.
+ * r1 = machine nr, r2 = atags pointer.
  *
  * This code is mostly position independent, so if you link the kernel at
  * 0xc0008000, you call this at __pa(0xc0008000).
@@ -85,6 +89,7 @@ ENTRY(stext)
        bl      __lookup_machine_type           @ r5=machinfo
        movs    r8, r5                          @ invalid machine (r5=0)?
        beq     __error_a                       @ yes, error 'a'
+       bl      __vet_atags
        bl      __create_page_tables
 
        /*
index 842361777d4e63782a96535c6c50cfbf3faedd19..93b7f8e22dcc1b3b69aa424c60d0a91bed19f772 100644 (file)
@@ -44,6 +44,10 @@ static const char *processor_modes[] = {
   "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
 };
 
+static const char *isa_modes[] = {
+  "ARM" , "Thumb" , "Jazelle", "ThumbEE"
+};
+
 extern void setup_mm_for_reboot(char mode);
 
 static volatile int hlt_counter;
@@ -230,11 +234,11 @@ void __show_regs(struct pt_regs *regs)
        buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
        buf[4] = '\0';
 
-       printk("Flags: %s  IRQs o%s  FIQs o%s  Mode %s%s  Segment %s\n",
+       printk("Flags: %s  IRQs o%s  FIQs o%s  Mode %s  ISA %s  Segment %s\n",
                buf, interrupts_enabled(regs) ? "n" : "ff",
                fast_interrupts_enabled(regs) ? "n" : "ff",
                processor_modes[processor_mode(regs)],
-               thumb_mode(regs) ? " (T)" : "",
+               isa_modes[isa_mode(regs)],
                get_fs() == get_ds() ? "kernel" : "user");
 #ifdef CONFIG_CPU_CP15
        {
index 650eac1bc0a6f2b5d3e10d382012c8e4850f56f0..5be2e987b8435b047bf168128364e3736eda30f4 100644 (file)
@@ -63,6 +63,8 @@ unsigned int processor_id;
 unsigned int __machine_arch_type;
 EXPORT_SYMBOL(__machine_arch_type);
 
+unsigned int __atags_pointer __initdata;
+
 unsigned int system_rev;
 EXPORT_SYMBOL(system_rev);
 
@@ -780,7 +782,9 @@ void __init setup_arch(char **cmdline_p)
        if (mdesc->soft_reboot)
                reboot_setup("s");
 
-       if (mdesc->boot_params)
+       if (__atags_pointer)
+               tags = phys_to_virt(__atags_pointer);
+       else if (mdesc->boot_params)
                tags = phys_to_virt(mdesc->boot_params);
 
        /*
index 26ca8ab3f62a7dc3df8f620178cf2695614ce44e..42e172cb0f49bfe2d0e40d9382d574234f712f3e 100644 (file)
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/dm9000.h>
+#include <linux/fb.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+
+#include <video/atmel_lcdc.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -271,6 +276,127 @@ static struct spi_board_info ek_spi_devices[] = {
 };
 
 
+/*
+ * LCD Controller
+ */
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static struct fb_videomode at91_tft_vga_modes[] = {
+       {
+               .name           = "TX09D50VM1CCA @ 60",
+               .refresh        = 60,
+               .xres           = 240,          .yres           = 320,
+               .pixclock       = KHZ2PICOS(4965),
+
+               .left_margin    = 1,            .right_margin   = 33,
+               .upper_margin   = 1,            .lower_margin   = 0,
+               .hsync_len      = 5,            .vsync_len      = 1,
+
+               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+};
+
+static struct fb_monspecs at91fb_default_monspecs = {
+       .manufacturer   = "HIT",
+       .monitor        = "TX09D50VM1CCA",
+
+       .modedb         = at91_tft_vga_modes,
+       .modedb_len     = ARRAY_SIZE(at91_tft_vga_modes),
+       .hfmin          = 15000,
+       .hfmax          = 64000,
+       .vfmin          = 50,
+       .vfmax          = 150,
+};
+
+#define AT91SAM9261_DEFAULT_LCDCON2    (ATMEL_LCDC_MEMOR_LITTLE \
+                                       | ATMEL_LCDC_DISTYPE_TFT    \
+                                       | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
+
+static void at91_lcdc_power_control(int on)
+{
+       if (on)
+               at91_set_gpio_value(AT91_PIN_PA12, 0);  /* power up */
+       else
+               at91_set_gpio_value(AT91_PIN_PA12, 1);  /* power down */
+}
+
+/* Driver datas */
+static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+       .default_bpp                    = 16,
+       .default_dmacon                 = ATMEL_LCDC_DMAEN,
+       .default_lcdcon2                = AT91SAM9261_DEFAULT_LCDCON2,
+       .default_monspecs               = &at91fb_default_monspecs,
+       .atmel_lcdfb_power_control      = at91_lcdc_power_control,
+       .guard_time                     = 1,
+};
+
+#else
+static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+#endif
+
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button ek_buttons[] = {
+       {
+               .gpio           = AT91_PIN_PA27,
+               .keycode        = BTN_0,
+               .desc           = "Button 0",
+               .active_low     = 1,
+       },
+       {
+               .gpio           = AT91_PIN_PA26,
+               .keycode        = BTN_1,
+               .desc           = "Button 1",
+               .active_low     = 1,
+       },
+       {
+               .gpio           = AT91_PIN_PA25,
+               .keycode        = BTN_2,
+               .desc           = "Button 2",
+               .active_low     = 1,
+       },
+       {
+               .gpio           = AT91_PIN_PA24,
+               .keycode        = BTN_3,
+               .desc           = "Button 3",
+               .active_low     = 1,
+       }
+};
+
+static struct gpio_keys_platform_data ek_button_data = {
+       .buttons        = ek_buttons,
+       .nbuttons       = ARRAY_SIZE(ek_buttons),
+};
+
+static struct platform_device ek_button_device = {
+       .name           = "gpio-keys",
+       .id             = -1,
+       .num_resources  = 0,
+       .dev            = {
+               .platform_data  = &ek_button_data,
+       }
+};
+
+static void __init ek_add_device_buttons(void)
+{
+       at91_set_gpio_input(AT91_PIN_PB27, 0);  /* btn0 */
+       at91_set_deglitch(AT91_PIN_PB27, 1);
+       at91_set_gpio_input(AT91_PIN_PB26, 0);  /* btn1 */
+       at91_set_deglitch(AT91_PIN_PB26, 1);
+       at91_set_gpio_input(AT91_PIN_PB25, 0);  /* btn2 */
+       at91_set_deglitch(AT91_PIN_PB25, 1);
+       at91_set_gpio_input(AT91_PIN_PB24, 0);  /* btn3 */
+       at91_set_deglitch(AT91_PIN_PB24, 1);
+
+       platform_device_register(&ek_button_device);
+}
+#else
+static void __init ek_add_device_buttons(void) {}
+#endif
+
 static void __init ek_board_init(void)
 {
        /* Serial */
@@ -296,6 +422,10 @@ static void __init ek_board_init(void)
        /* MMC */
        at91_add_device_mmc(0, &ek_mmc_data);
 #endif
+       /* LCD Controller */
+       at91_add_device_lcdc(&ek_lcdc_data);
+       /* Push Buttons */
+       ek_add_device_buttons();
 }
 
 MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
index c164c8e58ae6a037cdfbbf4b9b5a9842b9b094e2..2a1cc73390b79cd88943d7718c3fd3454d3c65fa 100644 (file)
@@ -26,6 +26,9 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
+#include <linux/fb.h>
+
+#include <video/atmel_lcdc.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -201,6 +204,65 @@ static struct at91_nand_data __initdata ek_nand_data = {
 };
 
 
+/*
+ * LCD Controller
+ */
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static struct fb_videomode at91_tft_vga_modes[] = {
+       {
+               .name           = "TX09D50VM1CCA @ 60",
+               .refresh        = 60,
+               .xres           = 240,          .yres           = 320,
+               .pixclock       = KHZ2PICOS(4965),
+
+               .left_margin    = 1,            .right_margin   = 33,
+               .upper_margin   = 1,            .lower_margin   = 0,
+               .hsync_len      = 5,            .vsync_len      = 1,
+
+               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+};
+
+static struct fb_monspecs at91fb_default_monspecs = {
+       .manufacturer   = "HIT",
+       .monitor        = "TX09D70VM1CCA",
+
+       .modedb         = at91_tft_vga_modes,
+       .modedb_len     = ARRAY_SIZE(at91_tft_vga_modes),
+       .hfmin          = 15000,
+       .hfmax          = 64000,
+       .vfmin          = 50,
+       .vfmax          = 150,
+};
+
+#define AT91SAM9263_DEFAULT_LCDCON2    (ATMEL_LCDC_MEMOR_LITTLE \
+                                       | ATMEL_LCDC_DISTYPE_TFT    \
+                                       | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
+
+static void at91_lcdc_power_control(int on)
+{
+       if (on)
+               at91_set_gpio_value(AT91_PIN_PD12, 0);  /* power up */
+       else
+               at91_set_gpio_value(AT91_PIN_PD12, 1);  /* power down */
+}
+
+/* Driver datas */
+static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+       .default_bpp                    = 16,
+       .default_dmacon                 = ATMEL_LCDC_DMAEN,
+       .default_lcdcon2                = AT91SAM9263_DEFAULT_LCDCON2,
+       .default_monspecs               = &at91fb_default_monspecs,
+       .atmel_lcdfb_power_control      = at91_lcdc_power_control,
+       .guard_time                     = 1,
+};
+
+#else
+static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+#endif
+
+
 /*
  * AC97
  */
@@ -230,6 +292,8 @@ static void __init ek_board_init(void)
        at91_add_device_nand(&ek_nand_data);
        /* I2C */
        at91_add_device_i2c();
+       /* LCD Controller */
+       at91_add_device_lcdc(&ek_lcdc_data);
        /* AC97 */
        at91_add_device_ac97(&ek_ac97_data);
 }
index a8f88cd299056ae1b52a673b2dd1b69b11de5ca0..99ac2e55774dcdf1c9b316ec9972a5d267765f89 100644 (file)
@@ -4,7 +4,8 @@
 #
 
 # Common objects
-obj-y                  := time.o irq.o serial.o io.o id.o psc.o
+obj-y                  := time.o irq.o clock.o serial.o io.o id.o psc.o \
+                          gpio.o mux.o
 
 # Board specific
 obj-$(CONFIG_MACH_DAVINCI_EVM)  += board-evm.o
index 633c12e43044528084b2275daf69143a1a0967b5..9e4024c4965f09a0ff24f71dc81df925bb93ed37 100644 (file)
@@ -32,6 +32,7 @@
 void __init davinci_psc_init(void);
 void __init davinci_irq_init(void);
 void __init davinci_map_common_io(void);
+void __init davinci_init_common_hw(void);
 
 /* NOR Flash base address set to CS0 by default */
 #define NOR_FLASH_PHYS 0x02000000
@@ -116,6 +117,7 @@ static __init void davinci_evm_init(void)
 
 static __init void davinci_evm_irq_init(void)
 {
+       davinci_init_common_hw();
        davinci_irq_init();
 }
 
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
new file mode 100644 (file)
index 0000000..139ceaa
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * TI DaVinci clock config file
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/psc.h>
+#include "clock.h"
+
+/* PLL/Reset register offsets */
+#define PLLM           0x110
+
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+static DEFINE_SPINLOCK(clockfw_lock);
+
+static unsigned int commonrate;
+static unsigned int armrate;
+static unsigned int fixedrate = 27000000;      /* 27 MHZ */
+
+extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable);
+
+/*
+ * Returns a clock. Note that we first try to use device id on the bus
+ * and clock name. If this fails, we try to use clock name only.
+ */
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       struct clk *p, *clk = ERR_PTR(-ENOENT);
+       int idno;
+
+       if (dev == NULL || dev->bus != &platform_bus_type)
+               idno = -1;
+       else
+               idno = to_platform_device(dev)->id;
+
+       mutex_lock(&clocks_mutex);
+
+       list_for_each_entry(p, &clocks, node) {
+               if (p->id == idno &&
+                   strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+                       clk = p;
+                       goto found;
+               }
+       }
+
+       list_for_each_entry(p, &clocks, node) {
+               if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+                       clk = p;
+                       break;
+               }
+       }
+
+found:
+       mutex_unlock(&clocks_mutex);
+
+       return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+       if (clk && !IS_ERR(clk))
+               module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+static int __clk_enable(struct clk *clk)
+{
+       if (clk->flags & ALWAYS_ENABLED)
+               return 0;
+
+       davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
+       return 0;
+}
+
+static void __clk_disable(struct clk *clk)
+{
+       if (clk->usecount)
+               return;
+
+       davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
+}
+
+int clk_enable(struct clk *clk)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       if (clk == NULL || IS_ERR(clk))
+               return -EINVAL;
+
+       if (clk->usecount++ == 0) {
+               spin_lock_irqsave(&clockfw_lock, flags);
+               ret = __clk_enable(clk);
+               spin_unlock_irqrestore(&clockfw_lock, flags);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+       unsigned long flags;
+
+       if (clk == NULL || IS_ERR(clk))
+               return;
+
+       if (clk->usecount > 0 && !(--clk->usecount)) {
+               spin_lock_irqsave(&clockfw_lock, flags);
+               __clk_disable(clk);
+               spin_unlock_irqrestore(&clockfw_lock, flags);
+       }
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       if (clk == NULL || IS_ERR(clk))
+               return -EINVAL;
+
+       return *(clk->rate);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       if (clk == NULL || IS_ERR(clk))
+               return -EINVAL;
+
+       return *(clk->rate);
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       if (clk == NULL || IS_ERR(clk))
+               return -EINVAL;
+
+       /* changing the clk rate is not supported */
+       return -EINVAL;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_register(struct clk *clk)
+{
+       if (clk == NULL || IS_ERR(clk))
+               return -EINVAL;
+
+       mutex_lock(&clocks_mutex);
+       list_add(&clk->node, &clocks);
+       mutex_unlock(&clocks_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+       if (clk == NULL || IS_ERR(clk))
+               return;
+
+       mutex_lock(&clocks_mutex);
+       list_del(&clk->node);
+       mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static struct clk davinci_clks[] = {
+       {
+               .name = "ARMCLK",
+               .rate = &armrate,
+               .lpsc = -1,
+               .flags = ALWAYS_ENABLED,
+       },
+       {
+               .name = "UART",
+               .rate = &fixedrate,
+               .lpsc = DAVINCI_LPSC_UART0,
+       },
+       {
+               .name = "EMACCLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
+       },
+       {
+               .name = "I2CCLK",
+               .rate = &fixedrate,
+               .lpsc = DAVINCI_LPSC_I2C,
+       },
+       {
+               .name = "IDECLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_ATA,
+       },
+       {
+               .name = "McBSPCLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_McBSP,
+       },
+       {
+               .name = "MMCSDCLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_MMC_SD,
+       },
+       {
+               .name = "SPICLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_SPI,
+       },
+       {
+               .name = "gpio",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_GPIO,
+       },
+       {
+               .name = "AEMIFCLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_AEMIF,
+               .usecount = 1,
+       }
+};
+
+int __init davinci_clk_init(void)
+{
+       struct clk *clkp;
+       int count = 0;
+       u32 pll_mult;
+
+       pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM);
+       commonrate = ((pll_mult + 1) * 27000000) / 6;
+       armrate = ((pll_mult + 1) * 27000000) / 2;
+
+       for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks);
+            count++, clkp++) {
+               clk_register(clkp);
+
+               /* Turn on clocks that have been enabled in the
+                * table above */
+               if (clkp->usecount)
+                       clk_enable(clkp);
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static void *davinci_ck_start(struct seq_file *m, loff_t *pos)
+{
+       return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       ++*pos;
+       return NULL;
+}
+
+static void davinci_ck_stop(struct seq_file *m, void *v)
+{
+}
+
+static int davinci_ck_show(struct seq_file *m, void *v)
+{
+       struct clk *cp;
+
+       list_for_each_entry(cp, &clocks, node)
+               seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount);
+
+       return 0;
+}
+
+static struct seq_operations davinci_ck_op = {
+       .start  = davinci_ck_start,
+       .next   = davinci_ck_next,
+       .stop   = davinci_ck_stop,
+       .show   = davinci_ck_show
+};
+
+static int davinci_ck_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &davinci_ck_op);
+}
+
+static struct file_operations proc_davinci_ck_operations = {
+       .open           = davinci_ck_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int __init davinci_ck_proc_init(void)
+{
+       struct proc_dir_entry *entry;
+
+       entry = create_proc_entry("davinci_clocks", 0, NULL);
+       if (entry)
+               entry->proc_fops = &proc_davinci_ck_operations;
+       return 0;
+
+}
+__initcall(davinci_ck_proc_init);
+#endif /* CONFIG_DEBUG_PROC_FS */
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
new file mode 100644 (file)
index 0000000..ed47079
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * TI DaVinci clock definitions
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_DAVINCI_CLOCK_H
+#define __ARCH_ARM_DAVINCI_CLOCK_H
+
+struct clk {
+       struct list_head        node;
+       struct module           *owner;
+       const char              *name;
+       unsigned int            *rate;
+       int                     id;
+       __s8                    usecount;
+       __u8                    flags;
+       __u8                    lpsc;
+};
+
+/* Clock flags */
+#define RATE_CKCTL             1
+#define RATE_FIXED             2
+#define RATE_PROPAGATES                4
+#define VIRTUAL_CLOCK          8
+#define ALWAYS_ENABLED         16
+#define ENABLE_REG_32BIT       32
+
+#endif
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c
new file mode 100644 (file)
index 0000000..9c67886
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/gpio.h>
+
+#include <asm/mach/irq.h>
+
+static DEFINE_SPINLOCK(gpio_lock);
+static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO);
+
+int gpio_request(unsigned gpio, const char *tag)
+{
+       if (gpio >= DAVINCI_N_GPIO)
+               return -EINVAL;
+
+       if (test_and_set_bit(gpio, gpio_in_use))
+               return -EBUSY;
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+       if (gpio >= DAVINCI_N_GPIO)
+               return;
+
+       clear_bit(gpio, gpio_in_use);
+}
+EXPORT_SYMBOL(gpio_free);
+
+/* create a non-inlined version */
+static struct gpio_controller *__iomem gpio2controller(unsigned gpio)
+{
+       return __gpio_to_controller(gpio);
+}
+
+/*
+ * Assuming the pin is muxed as a gpio output, set its output value.
+ */
+void __gpio_set(unsigned gpio, int value)
+{
+       struct gpio_controller *__iomem g = gpio2controller(gpio);
+
+       __raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data);
+}
+EXPORT_SYMBOL(__gpio_set);
+
+
+/*
+ * Read the pin's value (works even if it's set up as output);
+ * returns zero/nonzero.
+ *
+ * Note that changes are synched to the GPIO clock, so reading values back
+ * right after you've set them may give old values.
+ */
+int __gpio_get(unsigned gpio)
+{
+       struct gpio_controller *__iomem g = gpio2controller(gpio);
+
+       return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+}
+EXPORT_SYMBOL(__gpio_get);
+
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * board setup code *MUST* set PINMUX0 and PINMUX1 as
+ * needed, and enable the GPIO clock.
+ */
+
+int gpio_direction_input(unsigned gpio)
+{
+       struct gpio_controller *__iomem g = gpio2controller(gpio);
+       u32 temp;
+       u32 mask;
+
+       if (!g)
+               return -EINVAL;
+
+       spin_lock(&gpio_lock);
+       mask = __gpio_mask(gpio);
+       temp = __raw_readl(&g->dir);
+       temp |= mask;
+       __raw_writel(temp, &g->dir);
+       spin_unlock(&gpio_lock);
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+       struct gpio_controller *__iomem g = gpio2controller(gpio);
+       u32 temp;
+       u32 mask;
+
+       if (!g)
+               return -EINVAL;
+
+       spin_lock(&gpio_lock);
+       mask = __gpio_mask(gpio);
+       temp = __raw_readl(&g->dir);
+       temp &= ~mask;
+       __raw_writel(mask, value ? &g->set_data : &g->clr_data);
+       __raw_writel(temp, &g->dir);
+       spin_unlock(&gpio_lock);
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*
+ * We expect irqs will normally be set up as input pins, but they can also be
+ * used as output pins ... which is convenient for testing.
+ *
+ * NOTE:  GPIO0..GPIO7 also have direct INTC hookups, which work in addition
+ * to their GPIOBNK0 irq (but with a bit less overhead).  But we don't have
+ * a good way to hook those up ...
+ *
+ * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also
+ * serve as EDMA event triggers.
+ */
+
+static void gpio_irq_disable(unsigned irq)
+{
+       struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+       u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+       __raw_writel(mask, &g->clr_falling);
+       __raw_writel(mask, &g->clr_rising);
+}
+
+static void gpio_irq_enable(unsigned irq)
+{
+       struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+       u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+       if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING)
+               __raw_writel(mask, &g->set_falling);
+       if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING)
+               __raw_writel(mask, &g->set_rising);
+}
+
+static int gpio_irq_type(unsigned irq, unsigned trigger)
+{
+       struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+       u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+       if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+               return -EINVAL;
+
+       irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
+       irq_desc[irq].status |= trigger;
+
+       __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
+                    ? &g->set_falling : &g->clr_falling);
+       __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
+                    ? &g->set_rising : &g->clr_rising);
+       return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+       .name           = "GPIO",
+       .enable         = gpio_irq_enable,
+       .disable        = gpio_irq_disable,
+       .set_type       = gpio_irq_type,
+};
+
+static void
+gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+       struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+       u32 mask = 0xffff;
+
+       /* we only care about one bank */
+       if (irq & 1)
+               mask <<= 16;
+
+       /* temporarily mask (level sensitive) parent IRQ */
+       desc->chip->ack(irq);
+       while (1) {
+               u32             status;
+               struct irq_desc *gpio;
+               int             n;
+               int             res;
+
+               /* ack any irqs */
+               status = __raw_readl(&g->intstat) & mask;
+               if (!status)
+                       break;
+               __raw_writel(status, &g->intstat);
+               if (irq & 1)
+                       status >>= 16;
+
+               /* now demux them to the right lowlevel handler */
+               n = (int)get_irq_data(irq);
+               gpio = &irq_desc[n];
+               while (status) {
+                       res = ffs(status);
+                       n += res;
+                       gpio += res;
+                       desc_handle_irq(n - 1, gpio - 1);
+                       status >>= res;
+               }
+       }
+       desc->chip->unmask(irq);
+       /* now it may re-trigger */
+}
+
+/*
+ * NOTE:  for suspend/resume, probably best to make a sysdev (and class)
+ * with its suspend/resume calls hooking into the results of the set_wake()
+ * calls ... so if no gpios are wakeup events the clock can be disabled,
+ * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
+ * can be set appropriately for GPIOV33 pins.
+ */
+
+static int __init davinci_gpio_irq_setup(void)
+{
+       unsigned        gpio, irq, bank;
+       struct clk      *clk;
+
+       clk = clk_get(NULL, "gpio");
+       if (IS_ERR(clk)) {
+               printk(KERN_ERR "Error %ld getting gpio clock?\n",
+                      PTR_ERR(clk));
+               return 0;
+       }
+
+       clk_enable(clk);
+
+       for (gpio = 0, irq = gpio_to_irq(0), bank = IRQ_GPIOBNK0;
+            gpio < DAVINCI_N_GPIO; bank++) {
+               struct gpio_controller  *__iomem g = gpio2controller(gpio);
+               unsigned                i;
+
+               __raw_writel(~0, &g->clr_falling);
+               __raw_writel(~0, &g->clr_rising);
+
+               /* set up all irqs in this bank */
+               set_irq_chained_handler(bank, gpio_irq_handler);
+               set_irq_chip_data(bank, g);
+               set_irq_data(bank, (void *)irq);
+
+               for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO;
+                    i++, irq++, gpio++) {
+                       set_irq_chip(irq, &gpio_irqchip);
+                       set_irq_chip_data(irq, g);
+                       set_irq_handler(irq, handle_simple_irq);
+                       set_irq_flags(irq, IRQF_VALID);
+               }
+       }
+
+       /* BINTEN -- per-bank interrupt enable. genirq would also let these
+        * bits be set/cleared dynamically.
+        */
+       __raw_writel(0x1f, (void *__iomem)
+                    IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
+
+       printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
+
+       return 0;
+}
+
+arch_initcall(davinci_gpio_irq_setup);
index 87fae6fb6ecf9b5d5447dce953a99aa42ab7c9d8..47787ff84a6ad19f9fd9ab455e9cc4d1762bdbfd 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/memory.h>
 
 #include <asm/mach/map.h>
+#include <asm/arch/clock.h>
 
 extern void davinci_check_revision(void);
 
@@ -49,3 +50,8 @@ void __init davinci_map_common_io(void)
         */
        davinci_check_revision();
 }
+
+void __init davinci_init_common_hw(void)
+{
+       davinci_clk_init();
+}
diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c
new file mode 100644 (file)
index 0000000..92d26bd
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * DaVinci pin multiplexing configurations
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+
+#include <asm/arch/mux.h>
+
+/* System control register offsets */
+#define PINMUX0         0x00
+#define PINMUX1         0x04
+
+static DEFINE_SPINLOCK(mux_lock);
+
+void davinci_mux_peripheral(unsigned int mux, unsigned int enable)
+{
+       u32 pinmux, muxreg = PINMUX0;
+
+       if (mux >= DAVINCI_MUX_LEVEL2) {
+               muxreg = PINMUX1;
+               mux -= DAVINCI_MUX_LEVEL2;
+       }
+
+       spin_lock(&mux_lock);
+       pinmux = davinci_readl(DAVINCI_SYSTEM_MODULE_BASE + muxreg);
+       if (enable)
+               pinmux |= (1 << mux);
+       else
+               pinmux &= ~(1 << mux);
+       davinci_writel(pinmux, DAVINCI_SYSTEM_MODULE_BASE + muxreg);
+       spin_unlock(&mux_lock);
+}
index e1b0050283a681f78b2061d594be2a91c7be30bb..1334416559ad264cf3fd3f69ed68a8333cb56303 100644 (file)
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/arch/psc.h>
+#include <asm/arch/mux.h>
 
-#define PTCMD       __REG(0x01C41120)
-#define PDSTAT      __REG(0x01C41200)
-#define PDCTL1      __REG(0x01C41304)
-#define EPCPR       __REG(0x01C41070)
-#define PTSTAT      __REG(0x01C41128)
+/* PSC register offsets */
+#define EPCPR          0x070
+#define PTCMD          0x120
+#define PTSTAT         0x128
+#define PDSTAT         0x200
+#define PDCTL1         0x304
+#define MDSTAT         0x800
+#define MDCTL          0xA00
 
-#define MDSTAT      IO_ADDRESS(0x01C41800)
-#define MDCTL       IO_ADDRESS(0x01C41A00)
-
-#define PINMUX0             __REG(0x01c40000)
-#define PINMUX1             __REG(0x01c40004)
-#define VDD3P3V_PWDN __REG(0x01C40048)
+/* System control register offsets */
+#define VDD3P3V_PWDN   0x48
 
 static void davinci_psc_mux(unsigned int id)
 {
        switch (id) {
        case DAVINCI_LPSC_ATA:
-               PINMUX0 |= (1 << 17) | (1 << 16);
+               davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1);
+               davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1);
                break;
        case DAVINCI_LPSC_MMC_SD:
                /* VDD power manupulations are done in U-Boot for CPMAC
                 * so applies to MMC as well
                 */
                /*Set up the pull regiter for MMC */
-               VDD3P3V_PWDN = 0x0;
-               PINMUX1 &= (~(1 << 9));
+               davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN);
+               davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0);
                break;
        case DAVINCI_LPSC_I2C:
-               PINMUX1 |= (1 << 7);
+               davinci_mux_peripheral(DAVINCI_MUX_I2C, 1);
                break;
        case DAVINCI_LPSC_McBSP:
-               PINMUX1 |= (1 << 10);
+               davinci_mux_peripheral(DAVINCI_MUX_ASP, 1);
                break;
        default:
                break;
@@ -67,33 +68,59 @@ static void davinci_psc_mux(unsigned int id)
 /* Enable or disable a PSC domain */
 void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
 {
-       volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id);
-       volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id);
+       u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask;
 
        if (id < 0)
                return;
 
+       mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
        if (enable)
-               *mdctl |= 0x00000003;   /* Enable Module */
+               mdctl |= 0x00000003;    /* Enable Module */
        else
-               *mdctl &= 0xFFFFFFF2;   /* Disable Module */
+               mdctl &= 0xFFFFFFF2;    /* Disable Module */
+       davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
+
+       pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT);
+       if ((pdstat & 0x00000001) == 0) {
+               pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+               pdctl1 |= 0x1;
+               davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+
+               ptcmd = 1 << domain;
+               davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
 
-       if ((PDSTAT & 0x00000001) == 0) {
-               PDCTL1 |= 0x1;
-               PTCMD = (1 << domain);
-               while ((((EPCPR >> domain) & 1) == 0));
+               do {
+                       epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+                                             EPCPR);
+               } while ((((epcpr >> domain) & 1) == 0));
 
-               PDCTL1 |= 0x100;
-               while (!(((PTSTAT >> domain) & 1) == 0));
+               pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+               pdctl1 |= 0x100;
+               davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+
+               do {
+                       ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+                                              PTSTAT);
+               } while (!(((ptstat >> domain) & 1) == 0));
        } else {
-               PTCMD = (1 << domain);
-               while (!(((PTSTAT >> domain) & 1) == 0));
+               ptcmd = 1 << domain;
+               davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
+
+               do {
+                       ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+                                              PTSTAT);
+               } while (!(((ptstat >> domain) & 1) == 0));
        }
 
        if (enable)
-               while (!((*mdstat & 0x0000001F) == 0x3));
+               mdstat_mask = 0x3;
        else
-               while (!((*mdstat & 0x0000001F) == 0x2));
+               mdstat_mask = 0x2;
+
+       do {
+               mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+                                      MDSTAT + 4 * id);
+       } while (!((mdstat & 0x0000001F) == mdstat_mask));
 
        if (enable)
                davinci_psc_mux(id);
index 1c474cf709ca9b4a4241a112fceba2c1560244ea..a58b678006dff1ce50ef7ccaa86ffc1cc0b9fe1a 100644 (file)
 #include <linux/module.h>
 #include <linux/string.h>
 
+#include <asm/errno.h>
 #include <asm/arch/imxfb.h>
 #include <asm/hardware.h>
 #include <asm/arch/imx-regs.h>
 
 #include <asm/mach/map.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/gpio.h>
+
+unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG];
 
 void imx_gpio_mode(int gpio_mode)
 {
@@ -95,6 +99,120 @@ void imx_gpio_mode(int gpio_mode)
 
 EXPORT_SYMBOL(imx_gpio_mode);
 
+int imx_gpio_request(unsigned gpio, const char *label)
+{
+       if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+               printk(KERN_ERR "imx_gpio: Attempt to request nonexistent GPIO %d for \"%s\"\n",
+                       gpio, label ? label : "?");
+               return -EINVAL;
+
+       if(test_and_set_bit(gpio, imx_gpio_alloc_map)) {
+               printk(KERN_ERR "imx_gpio: GPIO %d already used. Allocation for \"%s\" failed\n",
+                       gpio, label ? label : "?");
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_request);
+
+void imx_gpio_free(unsigned gpio)
+{
+       if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+               return;
+
+       clear_bit(gpio, imx_gpio_alloc_map);
+}
+
+EXPORT_SYMBOL(imx_gpio_free);
+
+int imx_gpio_direction_input(unsigned gpio)
+{
+       imx_gpio_mode(gpio| GPIO_IN);
+       return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_input);
+
+int imx_gpio_direction_output(unsigned gpio, int value)
+{
+       imx_gpio_set_value(gpio, value);
+       imx_gpio_mode(gpio| GPIO_OUT);
+       return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_output);
+
+int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+                               int alloc_mode, const char *label)
+{
+       const int *p = pin_list;
+       int i;
+       unsigned gpio;
+       unsigned mode;
+
+       for (i = 0; i < count; i++) {
+               gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+               mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK);
+
+               if (gpio >= (GPIO_PORT_MAX + 1) * 32)
+                       goto setup_error;
+
+               if (alloc_mode & IMX_GPIO_ALLOC_MODE_RELEASE)
+                       imx_gpio_free(gpio);
+               else if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_NO_ALLOC))
+                       if (imx_gpio_request(gpio, label))
+                               if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+                                       goto setup_error;
+
+               if (!(alloc_mode & (IMX_GPIO_ALLOC_MODE_ALLOC_ONLY |
+                                   IMX_GPIO_ALLOC_MODE_RELEASE)))
+                       imx_gpio_mode(gpio | mode);
+
+               p++;
+       }
+       return 0;
+
+setup_error:
+       if(alloc_mode & (IMX_GPIO_ALLOC_MODE_NO_ALLOC |
+                        IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+               return -EINVAL;
+
+       while (p != pin_list) {
+               p--;
+               gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+               imx_gpio_free(gpio);
+       }
+
+       return -EINVAL;
+}
+
+EXPORT_SYMBOL(imx_gpio_setup_multiple_pins);
+
+void __imx_gpio_set_value(unsigned gpio, int value)
+{
+       imx_gpio_set_value_inline(gpio, value);
+}
+
+EXPORT_SYMBOL(__imx_gpio_set_value);
+
+int imx_gpio_to_irq(unsigned gpio)
+{
+       return IRQ_GPIOA(0) + gpio;
+}
+
+EXPORT_SYMBOL(imx_gpio_to_irq);
+
+int imx_irq_to_gpio(unsigned irq)
+{
+       if (irq < IRQ_GPIOA(0))
+               return -EINVAL;
+       return irq - IRQ_GPIOA(0);
+}
+
+EXPORT_SYMBOL(imx_irq_to_gpio);
+
 /*
  *  get the system pll clock in Hz
  *
index 6960a9d042175d824d080c38cb8e35b21148ef69..010f6fa984a65e7f05262fa5ec70edda8ee8b34b 100644 (file)
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2000-2001 Deep Blue Solutions
  *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.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
@@ -15,6 +16,7 @@
 #include <linux/irq.h>
 #include <linux/time.h>
 #include <linux/clocksource.h>
+#include <linux/clockchips.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -25,7 +27,8 @@
 /* Use timer 1 as system timer */
 #define TIMER_BASE IMX_TIM1_BASE
 
-static unsigned long evt_diff;
+static struct clock_event_device clockevent_imx;
+static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
 
 /*
  * IRQ handler for the timer
@@ -33,25 +36,20 @@ static unsigned long evt_diff;
 static irqreturn_t
 imx_timer_interrupt(int irq, void *dev_id)
 {
+       struct clock_event_device *evt = &clockevent_imx;
        uint32_t tstat;
+       irqreturn_t ret = IRQ_NONE;
 
        /* clear the interrupt */
        tstat = IMX_TSTAT(TIMER_BASE);
        IMX_TSTAT(TIMER_BASE) = 0;
 
        if (tstat & TSTAT_COMP) {
-               do {
-
-                       write_seqlock(&xtime_lock);
-                       timer_tick();
-                       write_sequnlock(&xtime_lock);
-                       IMX_TCMP(TIMER_BASE) += evt_diff;
-
-               } while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE)
-                                       - IMX_TCN(TIMER_BASE)) < 0));
+               evt->event_handler(evt);
+               ret = IRQ_HANDLED;
        }
 
-       return IRQ_HANDLED;
+       return ret;
 }
 
 static struct irqaction imx_timer_irq = {
@@ -70,10 +68,8 @@ static void __init imx_timer_hardware_init(void)
         */
        IMX_TCTL(TIMER_BASE) = 0;
        IMX_TPRER(TIMER_BASE) = 0;
-       IMX_TCMP(TIMER_BASE) = LATCH - 1;
 
-       IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_IRQEN | TCTL_TEN;
-       evt_diff = LATCH;
+       IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_TEN;
 }
 
 cycle_t imx_get_cycles(void)
@@ -99,11 +95,108 @@ static int __init imx_clocksource_init(void)
        return 0;
 }
 
+static int imx_set_next_event(unsigned long evt,
+                                 struct clock_event_device *unused)
+{
+       unsigned long tcmp;
+
+       tcmp = IMX_TCN(TIMER_BASE) + evt;
+       IMX_TCMP(TIMER_BASE) = tcmp;
+
+       return (int32_t)(tcmp - IMX_TCN(TIMER_BASE)) < 0 ? -ETIME : 0;
+}
+
+#ifdef DEBUG
+static const char *clock_event_mode_label[]={
+       [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
+       [CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
+       [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
+       [CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED"
+};
+#endif /*DEBUG*/
+
+static void imx_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
+{
+       unsigned long flags;
+
+       /*
+        * The timer interrupt generation is disabled at least
+        * for enough time to call imx_set_next_event()
+        */
+       local_irq_save(flags);
+       /* Disable interrupt in GPT module */
+       IMX_TCTL(TIMER_BASE) &= ~TCTL_IRQEN;
+       if (mode != clockevent_mode) {
+               /* Set event time into far-far future */
+               IMX_TCMP(TIMER_BASE) = IMX_TCN(TIMER_BASE) - 3;
+               /* Clear pending interrupt */
+               IMX_TSTAT(TIMER_BASE) &= ~TSTAT_COMP;
+       }
+
+#ifdef DEBUG
+       printk(KERN_INFO "imx_set_mode: changing mode from %s to %s\n",
+               clock_event_mode_label[clockevent_mode], clock_event_mode_label[mode]);
+#endif /*DEBUG*/
+
+       /* Remember timer mode */
+       clockevent_mode = mode;
+       local_irq_restore(flags);
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               printk(KERN_ERR "imx_set_mode: Periodic mode is not supported for i.MX\n");
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               /*
+                * Do not put overhead of interrupt enable/disable into
+                * imx_set_next_event(), the core has about 4 minutes
+                * to call imx_set_next_event() or shutdown clock after
+                * mode switching
+                */
+               local_irq_save(flags);
+               IMX_TCTL(TIMER_BASE) |= TCTL_IRQEN;
+               local_irq_restore(flags);
+               break;
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_UNUSED:
+               /* Left event sources disabled, no more interrupts appears */
+               break;
+       }
+}
+
+static struct clock_event_device clockevent_imx = {
+       .name           = "imx_timer1",
+       .features       = CLOCK_EVT_FEAT_ONESHOT,
+       .shift          = 32,
+       .set_mode       = imx_set_mode,
+       .set_next_event = imx_set_next_event,
+       .rating         = 200,
+};
+
+static int __init imx_clockevent_init(void)
+{
+       clockevent_imx.mult = div_sc(imx_get_perclk1(), NSEC_PER_SEC,
+                                       clockevent_imx.shift);
+       clockevent_imx.max_delta_ns =
+               clockevent_delta2ns(0xfffffffe, &clockevent_imx);
+       clockevent_imx.min_delta_ns =
+               clockevent_delta2ns(0xf, &clockevent_imx);
+
+       clockevent_imx.cpumask = cpumask_of_cpu(0);
+
+       clockevents_register_device(&clockevent_imx);
+
+       return 0;
+}
+
+
 static void __init imx_timer_init(void)
 {
        imx_timer_hardware_init();
        imx_clocksource_init();
 
+       imx_clockevent_init();
+
        /*
         * Make irqs happen for the system timer
         */
index bc4871553f6ac489accea0b0146a1bd08b6609ba..bfe0c87e33976e96fad4f673fc3ca334d5dcbf81 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/hardware/iop_adma.h>
 
 #define IOP13XX_UART_XTAL 33334000
 #define IOP13XX_SETUP_DEBUG 0
@@ -236,19 +237,143 @@ static unsigned long iq8134x_probe_flash_size(void)
 }
 #endif
 
+/* ADMA Channels */
+static struct resource iop13xx_adma_0_resources[] = {
+       [0] = {
+               .start = IOP13XX_ADMA_PHYS_BASE(0),
+               .end = IOP13XX_ADMA_UPPER_PA(0),
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_IOP13XX_ADMA0_EOT,
+               .end = IRQ_IOP13XX_ADMA0_EOT,
+               .flags = IORESOURCE_IRQ
+       },
+       [2] = {
+               .start = IRQ_IOP13XX_ADMA0_EOC,
+               .end = IRQ_IOP13XX_ADMA0_EOC,
+               .flags = IORESOURCE_IRQ
+       },
+       [3] = {
+               .start = IRQ_IOP13XX_ADMA0_ERR,
+               .end = IRQ_IOP13XX_ADMA0_ERR,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct resource iop13xx_adma_1_resources[] = {
+       [0] = {
+               .start = IOP13XX_ADMA_PHYS_BASE(1),
+               .end = IOP13XX_ADMA_UPPER_PA(1),
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_IOP13XX_ADMA1_EOT,
+               .end = IRQ_IOP13XX_ADMA1_EOT,
+               .flags = IORESOURCE_IRQ
+       },
+       [2] = {
+               .start = IRQ_IOP13XX_ADMA1_EOC,
+               .end = IRQ_IOP13XX_ADMA1_EOC,
+               .flags = IORESOURCE_IRQ
+       },
+       [3] = {
+               .start = IRQ_IOP13XX_ADMA1_ERR,
+               .end = IRQ_IOP13XX_ADMA1_ERR,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct resource iop13xx_adma_2_resources[] = {
+       [0] = {
+               .start = IOP13XX_ADMA_PHYS_BASE(2),
+               .end = IOP13XX_ADMA_UPPER_PA(2),
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_IOP13XX_ADMA2_EOT,
+               .end = IRQ_IOP13XX_ADMA2_EOT,
+               .flags = IORESOURCE_IRQ
+       },
+       [2] = {
+               .start = IRQ_IOP13XX_ADMA2_EOC,
+               .end = IRQ_IOP13XX_ADMA2_EOC,
+               .flags = IORESOURCE_IRQ
+       },
+       [3] = {
+               .start = IRQ_IOP13XX_ADMA2_ERR,
+               .end = IRQ_IOP13XX_ADMA2_ERR,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static u64 iop13xx_adma_dmamask = DMA_64BIT_MASK;
+static struct iop_adma_platform_data iop13xx_adma_0_data = {
+       .hw_id = 0,
+       .pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop13xx_adma_1_data = {
+       .hw_id = 1,
+       .pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop13xx_adma_2_data = {
+       .hw_id = 2,
+       .pool_size = PAGE_SIZE,
+};
+
+/* The ids are fixed up later in iop13xx_platform_init */
+static struct platform_device iop13xx_adma_0_channel = {
+       .name = "iop-adma",
+       .id = 0,
+       .num_resources = 4,
+       .resource = iop13xx_adma_0_resources,
+       .dev = {
+               .dma_mask = &iop13xx_adma_dmamask,
+               .coherent_dma_mask = DMA_64BIT_MASK,
+               .platform_data = (void *) &iop13xx_adma_0_data,
+       },
+};
+
+static struct platform_device iop13xx_adma_1_channel = {
+       .name = "iop-adma",
+       .id = 0,
+       .num_resources = 4,
+       .resource = iop13xx_adma_1_resources,
+       .dev = {
+               .dma_mask = &iop13xx_adma_dmamask,
+               .coherent_dma_mask = DMA_64BIT_MASK,
+               .platform_data = (void *) &iop13xx_adma_1_data,
+       },
+};
+
+static struct platform_device iop13xx_adma_2_channel = {
+       .name = "iop-adma",
+       .id = 0,
+       .num_resources = 4,
+       .resource = iop13xx_adma_2_resources,
+       .dev = {
+               .dma_mask = &iop13xx_adma_dmamask,
+               .coherent_dma_mask = DMA_64BIT_MASK,
+               .platform_data = (void *) &iop13xx_adma_2_data,
+       },
+};
+
 void __init iop13xx_map_io(void)
 {
        /* Initialize the Static Page Table maps */
        iotable_init(iop13xx_std_desc, ARRAY_SIZE(iop13xx_std_desc));
 }
 
-static int init_uart = 0;
-static int init_i2c = 0;
+static int init_uart;
+static int init_i2c;
+static int init_adma;
 
 void __init iop13xx_platform_init(void)
 {
        int i;
-       u32 uart_idx, i2c_idx, plat_idx;
+       u32 uart_idx, i2c_idx, adma_idx, plat_idx;
        struct platform_device *iop13xx_devices[IQ81340_MAX_PLAT_DEVICES];
 
        /* set the bases so we can read the device id */
@@ -294,6 +419,12 @@ void __init iop13xx_platform_init(void)
                }
        }
 
+       if (init_adma == IOP13XX_INIT_ADMA_DEFAULT) {
+               init_adma |= IOP13XX_INIT_ADMA_0;
+               init_adma |= IOP13XX_INIT_ADMA_1;
+               init_adma |= IOP13XX_INIT_ADMA_2;
+       }
+
        plat_idx = 0;
        uart_idx = 0;
        i2c_idx = 0;
@@ -332,6 +463,56 @@ void __init iop13xx_platform_init(void)
                }
        }
 
+       /* initialize adma channel ids and capabilities */
+       adma_idx = 0;
+       for (i = 0; i < IQ81340_NUM_ADMA; i++) {
+               struct iop_adma_platform_data *plat_data;
+               if ((init_adma & (1 << i)) && IOP13XX_SETUP_DEBUG)
+                       printk(KERN_INFO
+                               "Adding adma%d to platform device list\n", i);
+               switch (init_adma & (1 << i)) {
+               case IOP13XX_INIT_ADMA_0:
+                       iop13xx_adma_0_channel.id = adma_idx++;
+                       iop13xx_devices[plat_idx++] = &iop13xx_adma_0_channel;
+                       plat_data = &iop13xx_adma_0_data;
+                       dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+                       dma_cap_set(DMA_XOR, plat_data->cap_mask);
+                       dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+                       dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+                       dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+                       dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+                       dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+                       break;
+               case IOP13XX_INIT_ADMA_1:
+                       iop13xx_adma_1_channel.id = adma_idx++;
+                       iop13xx_devices[plat_idx++] = &iop13xx_adma_1_channel;
+                       plat_data = &iop13xx_adma_1_data;
+                       dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+                       dma_cap_set(DMA_XOR, plat_data->cap_mask);
+                       dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+                       dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+                       dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+                       dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+                       dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+                       break;
+               case IOP13XX_INIT_ADMA_2:
+                       iop13xx_adma_2_channel.id = adma_idx++;
+                       iop13xx_devices[plat_idx++] = &iop13xx_adma_2_channel;
+                       plat_data = &iop13xx_adma_2_data;
+                       dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+                       dma_cap_set(DMA_XOR, plat_data->cap_mask);
+                       dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+                       dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+                       dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+                       dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+                       dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+                       dma_cap_set(DMA_PQ_XOR, plat_data->cap_mask);
+                       dma_cap_set(DMA_PQ_UPDATE, plat_data->cap_mask);
+                       dma_cap_set(DMA_PQ_ZERO_SUM, plat_data->cap_mask);
+                       break;
+               }
+       }
+
 #ifdef CONFIG_MTD_PHYSMAP
        iq8134x_flash_resource.end = iq8134x_flash_resource.start +
                                iq8134x_probe_flash_size() - 1;
@@ -399,5 +580,35 @@ static int __init iop13xx_init_i2c_setup(char *str)
        return 1;
 }
 
+static int __init iop13xx_init_adma_setup(char *str)
+{
+       if (str)        {
+               while (*str != '\0') {
+                       switch (*str) {
+                       case '0':
+                               init_adma |= IOP13XX_INIT_ADMA_0;
+                               break;
+                       case '1':
+                               init_adma |= IOP13XX_INIT_ADMA_1;
+                               break;
+                       case '2':
+                               init_adma |= IOP13XX_INIT_ADMA_2;
+                               break;
+                       case ',':
+                       case '=':
+                               break;
+                       default:
+                               PRINTK("\"iop13xx_init_adma\" malformed"
+                                           " at character: \'%c\'", *str);
+                               *(str + 1) = '\0';
+                               init_adma = IOP13XX_INIT_ADMA_DEFAULT;
+                       }
+                       str++;
+               }
+       }
+       return 1;
+}
+
+__setup("iop13xx_init_adma", iop13xx_init_adma_setup);
 __setup("iop13xx_init_uart", iop13xx_init_uart_setup);
 __setup("iop13xx_init_i2c", iop13xx_init_i2c_setup);
index d3dc278213da10892934032db9f75c241182a918..2476347ea62f13b5119a28e1fd6f185d76a8ad8f 100644 (file)
 #define IOP13XX_TPMI_MMR(dev)  IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12))
 #define IOP13XX_TPMI_MEM(dev)  IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13))
 #define IOP13XX_TPMI_CTRL(dev) IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10))
+#define IOP13XX_TPMI_IOP_CTRL(dev) (IOP13XX_TPMI_CTRL(dev) + 0x2000)
 #define IOP13XX_TPMI_MMR_SIZE      (SZ_4K - 1)
 #define IOP13XX_TPMI_MEM_SIZE      (255)
 #define IOP13XX_TPMI_MEM_CTRL      (SZ_1K - 1)
 #define IOP13XX_TPMI_RESOURCE_MMR  0
 #define IOP13XX_TPMI_RESOURCE_MEM  1
 #define IOP13XX_TPMI_RESOURCE_CTRL 2
-#define IOP13XX_TPMI_RESOURCE_IRQ  3
+#define IOP13XX_TPMI_RESOURCE_IOP_CTRL 3
+#define IOP13XX_TPMI_RESOURCE_IRQ  4
 
 static struct resource iop13xx_tpmi_0_resources[] = {
        [IOP13XX_TPMI_RESOURCE_MMR] = {
@@ -53,6 +55,11 @@ static struct resource iop13xx_tpmi_0_resources[] = {
                .end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
                .flags = IORESOURCE_MEM,
        },
+       [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+               .start = IOP13XX_TPMI_IOP_CTRL(0),
+               .end = IOP13XX_TPMI_IOP_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
        [IOP13XX_TPMI_RESOURCE_IRQ] = {
                .start = IRQ_IOP13XX_TPMI0_OUT,
                .end = IRQ_IOP13XX_TPMI0_OUT,
@@ -76,6 +83,11 @@ static struct resource iop13xx_tpmi_1_resources[] = {
                .end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
                .flags = IORESOURCE_MEM,
        },
+       [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+               .start = IOP13XX_TPMI_IOP_CTRL(1),
+               .end = IOP13XX_TPMI_IOP_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
        [IOP13XX_TPMI_RESOURCE_IRQ] = {
                .start = IRQ_IOP13XX_TPMI1_OUT,
                .end = IRQ_IOP13XX_TPMI1_OUT,
@@ -99,6 +111,11 @@ static struct resource iop13xx_tpmi_2_resources[] = {
                .end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
                .flags = IORESOURCE_MEM,
        },
+       [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+               .start = IOP13XX_TPMI_IOP_CTRL(2),
+               .end = IOP13XX_TPMI_IOP_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
        [IOP13XX_TPMI_RESOURCE_IRQ] = {
                .start = IRQ_IOP13XX_TPMI2_OUT,
                .end = IRQ_IOP13XX_TPMI2_OUT,
@@ -122,6 +139,11 @@ static struct resource iop13xx_tpmi_3_resources[] = {
                .end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
                .flags = IORESOURCE_MEM,
        },
+       [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+               .start = IOP13XX_TPMI_IOP_CTRL(3),
+               .end = IOP13XX_TPMI_IOP_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
        [IOP13XX_TPMI_RESOURCE_IRQ] = {
                .start = IRQ_IOP13XX_TPMI3_OUT,
                .end = IRQ_IOP13XX_TPMI3_OUT,
@@ -133,7 +155,7 @@ u64 iop13xx_tpmi_mask = DMA_64BIT_MASK;
 static struct platform_device iop13xx_tpmi_0_device = {
        .name = "iop-tpmi",
        .id = 0,
-       .num_resources = 4,
+       .num_resources = ARRAY_SIZE(iop13xx_tpmi_0_resources),
        .resource = iop13xx_tpmi_0_resources,
        .dev = {
                .dma_mask          = &iop13xx_tpmi_mask,
@@ -144,7 +166,7 @@ static struct platform_device iop13xx_tpmi_0_device = {
 static struct platform_device iop13xx_tpmi_1_device = {
        .name = "iop-tpmi",
        .id = 1,
-       .num_resources = 4,
+       .num_resources = ARRAY_SIZE(iop13xx_tpmi_1_resources),
        .resource = iop13xx_tpmi_1_resources,
        .dev = {
                .dma_mask          = &iop13xx_tpmi_mask,
@@ -155,7 +177,7 @@ static struct platform_device iop13xx_tpmi_1_device = {
 static struct platform_device iop13xx_tpmi_2_device = {
        .name = "iop-tpmi",
        .id = 2,
-       .num_resources = 4,
+       .num_resources = ARRAY_SIZE(iop13xx_tpmi_2_resources),
        .resource = iop13xx_tpmi_2_resources,
        .dev = {
                .dma_mask          = &iop13xx_tpmi_mask,
@@ -166,7 +188,7 @@ static struct platform_device iop13xx_tpmi_2_device = {
 static struct platform_device iop13xx_tpmi_3_device = {
        .name = "iop-tpmi",
        .id = 3,
-       .num_resources = 4,
+       .num_resources = ARRAY_SIZE(iop13xx_tpmi_3_resources),
        .resource = iop13xx_tpmi_3_resources,
        .dev = {
                .dma_mask          = &iop13xx_tpmi_mask,
index 5776fd8841155407f35cf7672f7e74aac6884bbf..2b086ab2668ca24bd990ef0219c2385c64f4921a 100644 (file)
@@ -180,6 +180,8 @@ static void __init glantank_init_machine(void)
        platform_device_register(&iop3xx_i2c1_device);
        platform_device_register(&glantank_flash_device);
        platform_device_register(&glantank_serial_device);
+       platform_device_register(&iop3xx_dma_0_channel);
+       platform_device_register(&iop3xx_dma_1_channel);
 
        pm_power_off = glantank_power_off;
 }
index d4eefbea1fe653b727cbffa7c3f9937f7458719e..98cfa1cd6bdb577c7bab28eb37a8c14c503cee8c 100644 (file)
@@ -298,9 +298,14 @@ static void __init iq31244_init_machine(void)
        platform_device_register(&iop3xx_i2c1_device);
        platform_device_register(&iq31244_flash_device);
        platform_device_register(&iq31244_serial_device);
+       platform_device_register(&iop3xx_dma_0_channel);
+       platform_device_register(&iop3xx_dma_1_channel);
 
        if (is_ep80219())
                pm_power_off = ep80219_power_off;
+
+       if (!is_80219())
+               platform_device_register(&iop3xx_aau_channel);
 }
 
 static int __init force_ep80219_setup(char *str)
index 8d9f49164a848f5411188bfd92d33001a4ae1d3e..18ad29f213b2a42759b97cacf11a78f3adfc9e1f 100644 (file)
@@ -181,6 +181,9 @@ static void __init iq80321_init_machine(void)
        platform_device_register(&iop3xx_i2c1_device);
        platform_device_register(&iq80321_flash_device);
        platform_device_register(&iq80321_serial_device);
+       platform_device_register(&iop3xx_dma_0_channel);
+       platform_device_register(&iop3xx_dma_1_channel);
+       platform_device_register(&iop3xx_aau_channel);
 }
 
 MACHINE_START(IQ80321, "Intel IQ80321")
index d55005d647816b395ee7af7e228297dd7f7462e1..390a97d39e5a5cbb08a8d5e9c1a6108a9fc76843 100644 (file)
@@ -245,6 +245,8 @@ static void __init n2100_init_machine(void)
        platform_device_register(&iop3xx_i2c0_device);
        platform_device_register(&n2100_flash_device);
        platform_device_register(&n2100_serial_device);
+       platform_device_register(&iop3xx_dma_0_channel);
+       platform_device_register(&iop3xx_dma_1_channel);
 
        pm_power_off = n2100_power_off;
 
index 2b063180687a1ecd8ae0351ee205c5485e63fd13..433188ebff2a6dd9f6ad04ab9b8c640b25f7067f 100644 (file)
@@ -136,6 +136,9 @@ static void __init iq80331_init_machine(void)
        platform_device_register(&iop33x_uart0_device);
        platform_device_register(&iop33x_uart1_device);
        platform_device_register(&iq80331_flash_device);
+       platform_device_register(&iop3xx_dma_0_channel);
+       platform_device_register(&iop3xx_dma_1_channel);
+       platform_device_register(&iop3xx_aau_channel);
 }
 
 MACHINE_START(IQ80331, "Intel IQ80331")
index 7889ce3cb08eda561cb032edeba4351bce11c840..416c09564cc6ead75b84b98bdb122527fdc0343a 100644 (file)
@@ -136,6 +136,9 @@ static void __init iq80332_init_machine(void)
        platform_device_register(&iop33x_uart0_device);
        platform_device_register(&iop33x_uart1_device);
        platform_device_register(&iq80332_flash_device);
+       platform_device_register(&iop3xx_dma_0_channel);
+       platform_device_register(&iop3xx_dma_1_channel);
+       platform_device_register(&iop3xx_aau_channel);
 }
 
 MACHINE_START(IQ80332, "Intel IQ80332")
index 060909870b505b582ee4a2ee684cdd9ddd311e67..61b2dfcb89d623dd401cd8226ec2d66bbf939690 100644 (file)
@@ -41,6 +41,22 @@ config ARCH_ADI_COYOTE
          Engineering Coyote Gateway Reference Platform. For more
          information on this platform, see <file:Documentation/arm/IXP4xx>.
 
+config MACH_GATEWAY7001
+       bool "Gateway 7001"
+       select PCI
+       help
+         Say 'Y' here if you want your kernel to support Gateway's
+         7001 Access Point. For more information on this platform,
+         see http://openwrt.org
+
+config MACH_WG302V2
+       bool "Netgear WG302 v2 / WAG302 v2"
+       select PCI
+       help
+         Say 'Y' here if you want your kernel to support Netgear's
+         WG302 v2 or WAG302 v2 Access Points. For more information
+         on this platform, see http://openwrt.org
+
 config ARCH_IXDP425
        bool "IXDP425"
        help
index 3b87c47e06cf893d6a74aa9fc161afdac6e426bf..77e00ade558589297aaa425558958a66a61fbffb 100644 (file)
@@ -13,6 +13,8 @@ obj-pci-$(CONFIG_MACH_GTWX5715)               += gtwx5715-pci.o
 obj-pci-$(CONFIG_MACH_NSLU2)           += nslu2-pci.o
 obj-pci-$(CONFIG_MACH_NAS100D)         += nas100d-pci.o
 obj-pci-$(CONFIG_MACH_DSMG600)         += dsmg600-pci.o
+obj-pci-$(CONFIG_MACH_GATEWAY7001)     += gateway7001-pci.o
+obj-pci-$(CONFIG_MACH_WG302V2)         += wg302v2-pci.o
 
 obj-y  += common.o
 
@@ -24,5 +26,7 @@ obj-$(CONFIG_MACH_GTWX5715)   += gtwx5715-setup.o
 obj-$(CONFIG_MACH_NSLU2)       += nslu2-setup.o nslu2-power.o
 obj-$(CONFIG_MACH_NAS100D)     += nas100d-setup.o nas100d-power.o
 obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o dsmg600-power.o
+obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o
+obj-$(CONFIG_MACH_WG302V2)     += wg302v2-setup.o
 
 obj-$(CONFIG_PCI)              += $(obj-pci-$(CONFIG_PCI)) common-pci.o
diff --git a/arch/arm/mach-ixp4xx/gateway7001-pci.c b/arch/arm/mach-ixp4xx/gateway7001-pci.c
new file mode 100644 (file)
index 0000000..6abf568
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * arch/arch/mach-ixp4xx/gateway7001-pci.c
+ *
+ * PCI setup routines for Gateway 7001
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ *     Copyright (C) 2002 Jungo Software Technologies.
+ *     Copyright (C) 2003 MontaVista Softwrae, Inc.
+ *
+ * Maintainer: Imre Kaloz <kaloz@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init gateway7001_pci_preinit(void)
+{
+       set_irq_type(IRQ_IXP4XX_GPIO10, IRQT_LOW);
+       set_irq_type(IRQ_IXP4XX_GPIO11, IRQT_LOW);
+
+       ixp4xx_pci_preinit();
+}
+
+static int __init gateway7001_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (slot == 1)
+               return IRQ_IXP4XX_GPIO11;
+       else if (slot == 2)
+               return IRQ_IXP4XX_GPIO10;
+       else return -1;
+}
+
+struct hw_pci gateway7001_pci __initdata = {
+       .nr_controllers = 1,
+       .preinit =        gateway7001_pci_preinit,
+       .swizzle =        pci_std_swizzle,
+       .setup =          ixp4xx_setup,
+       .scan =           ixp4xx_scan_bus,
+       .map_irq =        gateway7001_map_irq,
+};
+
+int __init gateway7001_pci_init(void)
+{
+       if (machine_is_gateway7001())
+               pci_common_init(&gateway7001_pci);
+       return 0;
+}
+
+subsys_initcall(gateway7001_pci_init);
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
new file mode 100644 (file)
index 0000000..3787683
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * arch/arm/mach-ixp4xx/gateway7001-setup.c
+ *
+ * Board setup for the Gateway 7001 board
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ *      Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <Kaloz@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data gateway7001_flash_data = {
+       .map_name       = "cfi_probe",
+       .width          = 2,
+};
+
+static struct resource gateway7001_flash_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device gateway7001_flash = {
+       .name           = "IXP4XX-Flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &gateway7001_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &gateway7001_flash_resource,
+};
+
+static struct resource gateway7001_uart_resource = {
+       .start  = IXP4XX_UART2_BASE_PHYS,
+       .end    = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+       .flags  = IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port gateway7001_uart_data[] = {
+       {
+               .mapbase        = IXP4XX_UART2_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART2,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+       },
+       { },
+};
+
+static struct platform_device gateway7001_uart = {
+       .name           = "serial8250",
+       .id             = PLAT8250_DEV_PLATFORM,
+       .dev                    = {
+               .platform_data  = gateway7001_uart_data,
+       },
+       .num_resources  = 1,
+       .resource       = &gateway7001_uart_resource,
+};
+
+static struct platform_device *gateway7001_devices[] __initdata = {
+       &gateway7001_flash,
+       &gateway7001_uart
+};
+
+static void __init gateway7001_init(void)
+{
+       ixp4xx_sys_init();
+
+       gateway7001_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+       gateway7001_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+       *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+       *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+       platform_add_devices(gateway7001_devices, ARRAY_SIZE(gateway7001_devices));
+}
+
+#ifdef CONFIG_MACH_GATEWAY7001
+MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
+       /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
+       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+       .map_io         = ixp4xx_map_io,
+       .init_irq       = ixp4xx_init_irq,
+       .timer          = &ixp4xx_timer,
+       .boot_params    = 0x0100,
+       .init_machine   = gateway7001_init,
+MACHINE_END
+#endif
index a66484b63d36b12b0dccd06770b3b3a9d2931a7a..0d5a42455820322c804d046233e7563826d66106 100644 (file)
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
+
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
-#include <asm/irq.h>
 #include <asm/arch/gtwx5715.h>
 #include <asm/mach/pci.h>
 
-extern void ixp4xx_pci_preinit(void);
-extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
-extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
-
-
 /*
  * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
  * Slot 0 isn't actually populated with a card connector but
index ec4f07950ec62745b300ae45e12c965434510048..d5008d8fc9a5af2eb24b85ff804410e4469f2ece 100644 (file)
 #include <linux/tty.h>
 #include <linux/serial_8250.h>
 #include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -24,6 +28,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
+#include <asm/delay.h>
 
 static struct flash_platform_data ixdp425_flash_data = {
        .map_name       = "cfi_probe",
@@ -44,6 +49,77 @@ static struct platform_device ixdp425_flash = {
        .resource       = &ixdp425_flash_resource,
 };
 
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
+
+static struct mtd_partition ixdp425_partitions[] = {
+       {
+               .name   = "ixp400 NAND FS 0",
+               .offset = 0,
+               .size   = SZ_8M
+       }, {
+               .name   = "ixp400 NAND FS 1",
+               .offset = MTDPART_OFS_APPEND,
+               .size   = MTDPART_SIZ_FULL
+       },
+};
+#endif
+
+static void
+ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+       struct nand_chip *this = mtd->priv;
+       int offset = (int)this->priv;
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               if (ctrl & NAND_NCE) {
+                       gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_LOW);
+                       udelay(5);
+               } else
+                       gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_HIGH);
+
+               offset = (ctrl & NAND_CLE) ? IXDP425_NAND_CMD_BYTE : 0;
+               offset |= (ctrl & NAND_ALE) ? IXDP425_NAND_ADDR_BYTE : 0;
+               this->priv = (void *)offset;
+       }
+
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, this->IO_ADDR_W + offset);
+}
+
+static struct platform_nand_data ixdp425_flash_nand_data = {
+       .chip = {
+               .chip_delay             = 30,
+               .options                = NAND_NO_AUTOINCR,
+#ifdef CONFIG_MTD_PARTITIONS
+               .part_probe_types       = part_probes,
+               .partitions             = ixdp425_partitions,
+               .nr_partitions          = ARRAY_SIZE(ixdp425_partitions),
+#endif
+       },
+       .ctrl = {
+               .cmd_ctrl               = ixdp425_flash_nand_cmd_ctrl
+       }
+};
+
+static struct resource ixdp425_flash_nand_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp425_flash_nand = {
+       .name           = "gen_nand",
+       .id             = -1,
+       .dev            = {
+               .platform_data = &ixdp425_flash_nand_data,
+       },
+       .num_resources  = 1,
+       .resource       = &ixdp425_flash_nand_resource,
+};
+#endif /* CONFIG_MTD_NAND_PLATFORM */
+
 static struct ixp4xx_i2c_pins ixdp425_i2c_gpio_pins = {
        .sda_pin        = IXDP425_SDA_PIN,
        .scl_pin        = IXDP425_SCL_PIN,
@@ -104,6 +180,10 @@ static struct platform_device ixdp425_uart = {
 static struct platform_device *ixdp425_devices[] __initdata = {
        &ixdp425_i2c_controller,
        &ixdp425_flash,
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+       &ixdp425_flash_nand,
+#endif
        &ixdp425_uart
 };
 
@@ -115,6 +195,22 @@ static void __init ixdp425_init(void)
        ixdp425_flash_resource.end =
                IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
 
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+       ixdp425_flash_nand_resource.start = IXP4XX_EXP_BUS_BASE(3),
+       ixdp425_flash_nand_resource.end   = IXP4XX_EXP_BUS_BASE(3) + 0x10 - 1;
+
+       gpio_line_config(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_OUT);
+
+       /* Configure expansion bus for NAND Flash */
+       *IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN |
+                         IXP4XX_EXP_BUS_STROBE_T(1) |  /* extend by 1 clock */
+                         IXP4XX_EXP_BUS_CYCLES(0) |    /* Intel cycles */
+                         IXP4XX_EXP_BUS_SIZE(0) |      /* 512bytes addr space*/
+                         IXP4XX_EXP_BUS_WR_EN |
+                         IXP4XX_EXP_BUS_BYTE_EN;       /* 8 bit data bus */
+#endif
+
        if (cpu_is_ixp43x()) {
                ixdp425_uart.num_resources = 1;
                ixdp425_uart_data[1].flags = 0;
diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c
new file mode 100644 (file)
index 0000000..6588f2c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * arch/arch/mach-ixp4xx/wg302v2-pci.c
+ *
+ * PCI setup routines for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ *     Copyright (C) 2002 Jungo Software Technologies.
+ *     Copyright (C) 2003 MontaVista Software, Inc.
+ *
+ * Maintainer: Imre Kaloz <kaloz@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init wg302v2_pci_preinit(void)
+{
+       set_irq_type(IRQ_IXP4XX_GPIO8, IRQT_LOW);
+       set_irq_type(IRQ_IXP4XX_GPIO9, IRQT_LOW);
+
+       ixp4xx_pci_preinit();
+}
+
+static int __init wg302v2_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (slot == 1)
+               return IRQ_IXP4XX_GPIO8;
+       else if (slot == 2)
+               return IRQ_IXP4XX_GPIO9;
+       else return -1;
+}
+
+struct hw_pci wg302v2_pci __initdata = {
+       .nr_controllers = 1,
+       .preinit =        wg302v2_pci_preinit,
+       .swizzle =        pci_std_swizzle,
+       .setup =          ixp4xx_setup,
+       .scan =           ixp4xx_scan_bus,
+       .map_irq =        wg302v2_map_irq,
+};
+
+int __init wg302v2_pci_init(void)
+{
+       if (machine_is_wg302v2())
+               pci_common_init(&wg302v2_pci);
+       return 0;
+}
+
+subsys_initcall(wg302v2_pci_init);
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
new file mode 100644 (file)
index 0000000..f7e09ad
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * arch/arm/mach-ixp4xx/wg302-setup.c
+ *
+ * Board setup for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <Kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ *      Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <kaloz@openwrt.org>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data wg302v2_flash_data = {
+       .map_name       = "cfi_probe",
+       .width          = 2,
+};
+
+static struct resource wg302v2_flash_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device wg302v2_flash = {
+       .name           = "IXP4XX-Flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &wg302v2_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &wg302v2_flash_resource,
+};
+
+static struct resource wg302v2_uart_resource = {
+       .start  = IXP4XX_UART2_BASE_PHYS,
+       .end    = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+       .flags  = IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port wg302v2_uart_data[] = {
+       {
+               .mapbase        = IXP4XX_UART2_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART2,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+       },
+       { },
+};
+
+static struct platform_device wg302v2_uart = {
+       .name           = "serial8250",
+       .id             = PLAT8250_DEV_PLATFORM,
+       .dev                    = {
+               .platform_data  = wg302v2_uart_data,
+       },
+       .num_resources  = 1,
+       .resource       = &wg302v2_uart_resource,
+};
+
+static struct platform_device *wg302v2_devices[] __initdata = {
+       &wg302v2_flash,
+       &wg302v2_uart,
+};
+
+static void __init wg302v2_init(void)
+{
+       ixp4xx_sys_init();
+
+       wg302v2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+       wg302v2_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+       *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+       *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+       platform_add_devices(wg302v2_devices, ARRAY_SIZE(wg302v2_devices));
+}
+
+#ifdef CONFIG_MACH_WG302V2
+MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
+       /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
+       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+       .map_io         = ixp4xx_map_io,
+       .init_irq       = ixp4xx_init_irq,
+       .timer          = &ixp4xx_timer,
+       .boot_params    = 0x0100,
+       .init_machine   = wg302v2_init,
+MACHINE_END
+#endif
index 56b7d337333a6fa43412c2b627ce18d35049625e..2a07a281fa8ae927f9957575f4c448a81bad8815 100644 (file)
@@ -3,7 +3,7 @@
 # Makefile for KS8695 architecture support
 #
 
-obj-y                          := cpu.o irq.o time.o devices.o
+obj-y                          := cpu.o irq.o time.o gpio.o devices.o
 obj-m                          :=
 obj-n                          :=
 obj-                           :=
diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c
new file mode 100644 (file)
index 0000000..b1aa3cb
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * arch/arm/mach-ks8695/gpio.c
+ *
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/gpio.h>
+
+/*
+ * Configure a GPIO line for either GPIO function, or its internal
+ * function (Interrupt, Timer, etc).
+ */
+static void __init_or_module ks8695_gpio_mode(unsigned int pin, short gpio)
+{
+       unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
+       unsigned long x, flags;
+
+       if (pin > KS8695_GPIO_5)        /* only GPIO 0..5 have internal functions */
+               return;
+
+       local_irq_save(flags);
+
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
+       if (gpio)                       /* GPIO: set bit to 0 */
+               x &= ~enable[pin];
+       else                            /* Internal function: set bit to 1 */
+               x |= enable[pin];
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
+
+       local_irq_restore(flags);
+}
+
+
+static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
+{
+       unsigned long x, flags;
+
+       if (pin > KS8695_GPIO_3)        /* only GPIO 0..3 can generate IRQ */
+               return -EINVAL;
+
+       local_irq_save(flags);
+
+       /* set pin as input */
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+       x &= ~IOPM_(pin);
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+       local_irq_restore(flags);
+
+       /* Set IRQ triggering type */
+       set_irq_type(gpio_irq[pin], type);
+
+       /* enable interrupt mode */
+       ks8695_gpio_mode(pin, 0);
+
+       return 0;
+}
+EXPORT_SYMBOL(ks8695_gpio_interrupt);
+
+
+
+/* .... Generic GPIO interface .............................................. */
+
+/*
+ * Configure the GPIO line as an input.
+ */
+int __init_or_module gpio_direction_input(unsigned int pin)
+{
+       unsigned long x, flags;
+
+       if (pin > KS8695_GPIO_15)
+               return -EINVAL;
+
+       /* set pin to GPIO mode */
+       ks8695_gpio_mode(pin, 1);
+
+       local_irq_save(flags);
+
+       /* set pin as input */
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+       x &= ~IOPM_(pin);
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+
+/*
+ * Configure the GPIO line as an output, with default state.
+ */
+int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state)
+{
+       unsigned long x, flags;
+
+       if (pin > KS8695_GPIO_15)
+               return -EINVAL;
+
+       /* set pin to GPIO mode */
+       ks8695_gpio_mode(pin, 1);
+
+       local_irq_save(flags);
+
+       /* set line state */
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+       if (state)
+               x |= (1 << pin);
+       else
+               x &= ~(1 << pin);
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+       /* set pin as output */
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+       x |= IOPM_(pin);
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+
+/*
+ * Set the state of an output GPIO line.
+ */
+void gpio_set_value(unsigned int pin, unsigned int state)
+{
+       unsigned long x, flags;
+
+       if (pin > KS8695_GPIO_15)
+               return;
+
+       local_irq_save(flags);
+
+       /* set output line state */
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+       if (state)
+               x |= (1 << pin);
+       else
+               x &= ~(1 << pin);
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+
+/*
+ * Read the state of a GPIO line.
+ */
+int gpio_get_value(unsigned int pin)
+{
+       unsigned long x;
+
+       if (pin > KS8695_GPIO_15)
+               return -EINVAL;
+
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+       return (x & (1 << pin)) != 0;
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+
+/*
+ * Map GPIO line to IRQ number.
+ */
+int gpio_to_irq(unsigned int pin)
+{
+       if (pin > KS8695_GPIO_3)        /* only GPIO 0..3 can generate IRQ */
+               return -EINVAL;
+
+       return gpio_irq[pin];
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+
+/*
+ * Map IRQ number to GPIO line.
+ */
+int irq_to_gpio(unsigned int irq)
+{
+       if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
+               return -EINVAL;
+
+       return (irq - KS8695_IRQ_EXTERN0);
+}
+EXPORT_SYMBOL(irq_to_gpio);
index 8f7c90a0593bce2ccf20669b1268703e8c4f4003..34a31caa6f9d6a83cbc379014fdbe8b88ccd7395 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/hardware.h>
-#include <asm/semaphore.h>
 
 struct clk {
        struct list_head        node;
@@ -25,21 +24,21 @@ struct clk {
 };
 
 static LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
 static DEFINE_SPINLOCK(clocks_lock);
 
 struct clk *clk_get(struct device *dev, const char *id)
 {
        struct clk *p, *clk = ERR_PTR(-ENOENT);
 
-       down(&clocks_sem);
+       mutex_lock(&clocks_mutex);
        list_for_each_entry(p, &clocks, node) {
                if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
                        clk = p;
                        break;
                }
        }
-       up(&clocks_sem);
+       mutex_unlock(&clocks_mutex);
 
        return clk;
 }
@@ -101,18 +100,18 @@ static struct clk clk_gpio27 = {
 
 int clk_register(struct clk *clk)
 {
-       down(&clocks_sem);
+       mutex_lock(&clocks_mutex);
        list_add(&clk->node, &clocks);
-       up(&clocks_sem);
+       mutex_unlock(&clocks_mutex);
        return 0;
 }
 EXPORT_SYMBOL(clk_register);
 
 void clk_unregister(struct clk *clk)
 {
-       down(&clocks_sem);
+       mutex_lock(&clocks_mutex);
        list_del(&clk->node);
-       up(&clocks_sem);
+       mutex_unlock(&clocks_mutex);
 }
 EXPORT_SYMBOL(clk_unregister);
 
index a1a900d16665fc8f58d6431306d1d4df0011dbee..aab27297b3c60da5937852e50a05cd70a27da5b8 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/hardware/scoop.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 
@@ -368,7 +369,7 @@ MACHINE_START(CORGI, "SHARP Corgi")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_corgi,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa25x_init_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -380,7 +381,7 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_corgi,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa25x_init_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -392,7 +393,7 @@ MACHINE_START(HUSKY, "SHARP Husky")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_corgi,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa25x_init_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
new file mode 100644 (file)
index 0000000..9a6faff
--- /dev/null
@@ -0,0 +1,11 @@
+extern struct platform_device pxamci_device;
+extern struct platform_device pxaudc_device;
+extern struct platform_device pxafb_device;
+extern struct platform_device ffuart_device;
+extern struct platform_device btuart_device;
+extern struct platform_device stuart_device;
+extern struct platform_device hwuart_device;
+extern struct platform_device pxai2c_device;
+extern struct platform_device pxai2s_device;
+extern struct platform_device pxaficp_device;
+extern struct platform_device pxartc_device;
index 4440babe7b97595dabe3330082ffd8aad9b6d674..93c4f31f127faa053dcd555f5fe7aa66fb5aee34 100644 (file)
 
 #include <asm/arch/pxa-regs.h>
 
-static struct dma_channel {
+struct dma_channel {
        char *name;
+       pxa_dma_prio prio;
        void (*irq_handler)(int, void *);
        void *data;
-} dma_channels[PXA_DMA_CHANNELS];
+};
 
+static struct dma_channel *dma_channels;
+static int num_dma_channels;
 
 int pxa_request_dma (char *name, pxa_dma_prio prio,
                         void (*irq_handler)(int, void *),
@@ -47,8 +50,9 @@ int pxa_request_dma (char *name, pxa_dma_prio prio,
 
        do {
                /* try grabbing a DMA channel with the requested priority */
-               pxa_for_each_dma_prio (i, prio) {
-                       if (!dma_channels[i].name) {
+               for (i = 0; i < num_dma_channels; i++) {
+                       if ((dma_channels[i].prio == prio) &&
+                           !dma_channels[i].name) {
                                found = 1;
                                break;
                        }
@@ -91,7 +95,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 {
        int i, dint = DINT;
 
-       for (i = 0; i < PXA_DMA_CHANNELS; i++) {
+       for (i = 0; i < num_dma_channels; i++) {
                if (dint & (1 << i)) {
                        struct dma_channel *channel = &dma_channels[i];
                        if (channel->name && channel->irq_handler) {
@@ -109,18 +113,32 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __init pxa_dma_init (void)
+int __init pxa_init_dma(int num_ch)
 {
-       int ret;
+       int i, ret;
 
-       ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
-       if (ret)
+       dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL);
+       if (dma_channels == NULL)
+               return -ENOMEM;
+
+       ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL);
+       if (ret) {
                printk (KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
-       return ret;
-}
+               kfree(dma_channels);
+               return ret;
+       }
 
-arch_initcall(pxa_dma_init);
+       /* dma channel priorities on pxa2xx processors:
+        * ch 0 - 3,  16 - 19  <--> (0) DMA_PRIO_HIGH
+        * ch 4 - 7,  20 - 23  <--> (1) DMA_PRIO_MEDIUM
+        * ch 8 - 15, 24 - 31  <--> (2) DMA_PRIO_LOW
+        */
+       for (i = 0; i < num_ch; i++)
+               dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW);
+
+       num_dma_channels = num_ch;
+       return 0;
+}
 
 EXPORT_SYMBOL(pxa_request_dma);
 EXPORT_SYMBOL(pxa_free_dma);
-
index 64b08b744f9f3fd12bcd06169e949b09881b39b8..296539b6359ca43af779f59e5fa078351c14195b 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/arch/irda.h>
 #include <asm/arch/i2c.h>
 
+#include "devices.h"
 #include "generic.h"
 
 /*
@@ -242,7 +243,7 @@ static struct resource pxamci_resources[] = {
 
 static u64 pxamci_dmamask = 0xffffffffUL;
 
-static struct platform_device pxamci_device = {
+struct platform_device pxamci_device = {
        .name           = "pxa2xx-mci",
        .id             = -1,
        .dev            = {
@@ -281,7 +282,7 @@ static struct resource pxa2xx_udc_resources[] = {
 
 static u64 udc_dma_mask = ~(u32)0;
 
-static struct platform_device udc_device = {
+struct platform_device pxaudc_device = {
        .name           = "pxa2xx-udc",
        .id             = -1,
        .resource       = pxa2xx_udc_resources,
@@ -307,7 +308,7 @@ static struct resource pxafb_resources[] = {
 
 static u64 fb_dma_mask = ~(u64)0;
 
-static struct platform_device pxafb_device = {
+struct platform_device pxafb_device = {
        .name           = "pxa2xx-fb",
        .id             = -1,
        .dev            = {
@@ -328,24 +329,24 @@ void __init set_pxa_fb_parent(struct device *parent_dev)
        pxafb_device.dev.parent = parent_dev;
 }
 
-static struct platform_device ffuart_device = {
+struct platform_device ffuart_device = {
        .name           = "pxa2xx-uart",
        .id             = 0,
 };
-static struct platform_device btuart_device = {
+struct platform_device btuart_device = {
        .name           = "pxa2xx-uart",
        .id             = 1,
 };
-static struct platform_device stuart_device = {
+struct platform_device stuart_device = {
        .name           = "pxa2xx-uart",
        .id             = 2,
 };
-static struct platform_device hwuart_device = {
+struct platform_device hwuart_device = {
        .name           = "pxa2xx-uart",
        .id             = 3,
 };
 
-static struct resource i2c_resources[] = {
+static struct resource pxai2c_resources[] = {
        {
                .start  = 0x40301680,
                .end    = 0x403016a3,
@@ -357,40 +358,19 @@ static struct resource i2c_resources[] = {
        },
 };
 
-static struct platform_device i2c_device = {
+struct platform_device pxai2c_device = {
        .name           = "pxa2xx-i2c",
        .id             = 0,
-       .resource       = i2c_resources,
-       .num_resources  = ARRAY_SIZE(i2c_resources),
+       .resource       = pxai2c_resources,
+       .num_resources  = ARRAY_SIZE(pxai2c_resources),
 };
 
-#ifdef CONFIG_PXA27x
-static struct resource i2c_power_resources[] = {
-       {
-               .start  = 0x40f00180,
-               .end    = 0x40f001a3,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = IRQ_PWRI2C,
-               .end    = IRQ_PWRI2C,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device i2c_power_device = {
-       .name           = "pxa2xx-i2c",
-       .id             = 1,
-       .resource       = i2c_power_resources,
-       .num_resources  = ARRAY_SIZE(i2c_resources),
-};
-#endif
-
 void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
 {
-       i2c_device.dev.platform_data = info;
+       pxai2c_device.dev.platform_data = info;
 }
 
-static struct resource i2s_resources[] = {
+static struct resource pxai2s_resources[] = {
        {
                .start  = 0x40400000,
                .end    = 0x40400083,
@@ -402,16 +382,16 @@ static struct resource i2s_resources[] = {
        },
 };
 
-static struct platform_device i2s_device = {
+struct platform_device pxai2s_device = {
        .name           = "pxa2xx-i2s",
        .id             = -1,
-       .resource       = i2s_resources,
-       .num_resources  = ARRAY_SIZE(i2s_resources),
+       .resource       = pxai2s_resources,
+       .num_resources  = ARRAY_SIZE(pxai2s_resources),
 };
 
 static u64 pxaficp_dmamask = ~(u32)0;
 
-static struct platform_device pxaficp_device = {
+struct platform_device pxaficp_device = {
        .name           = "pxa2xx-ir",
        .id             = -1,
        .dev            = {
@@ -425,42 +405,7 @@ void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
        pxaficp_device.dev.platform_data = info;
 }
 
-static struct platform_device pxartc_device = {
+struct platform_device pxartc_device = {
        .name           = "sa1100-rtc",
        .id             = -1,
 };
-
-static struct platform_device *devices[] __initdata = {
-       &pxamci_device,
-       &udc_device,
-       &pxafb_device,
-       &ffuart_device,
-       &btuart_device,
-       &stuart_device,
-       &pxaficp_device,
-       &i2c_device,
-#ifdef CONFIG_PXA27x
-       &i2c_power_device,
-#endif
-       &i2s_device,
-       &pxartc_device,
-};
-
-static int __init pxa_init(void)
-{
-       int cpuid, ret;
-
-       ret = platform_add_devices(devices, ARRAY_SIZE(devices));
-       if (ret)
-               return ret;
-
-       /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
-       cpuid = read_cpuid(CPUID_ID);
-       if (((cpuid >> 4) & 0xfff) == 0x2d0 ||
-           ((cpuid >> 4) & 0xfff) == 0x290)
-               ret = platform_device_register(&hwuart_device);
-
-       return ret;
-}
-
-subsys_initcall(pxa_init);
index e54a8dd63c17df1a5b2d12bb0fe2de306390ee18..91ab2ad8b34b78020da69be0bc71c5597c529ab4 100644 (file)
 struct sys_timer;
 
 extern struct sys_timer pxa_timer;
+extern void __init pxa_init_irq_low(void);
+extern void __init pxa_init_irq_high(void);
+extern void __init pxa_init_irq_gpio(int gpio_nr);
+extern void __init pxa25x_init_irq(void);
+extern void __init pxa27x_init_irq(void);
 extern void __init pxa_map_io(void);
-extern void __init pxa_init_irq(void);
 
 extern unsigned int get_clk_frequency_khz(int info);
 
index 64df44043a654f88826edd7e2e65470d41bdf455..465108da285103be616ecfd8f13f9f5d302bcb63 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/arch/mmc.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /* TODO:
  * - add pxa2xx_audio_ops_t device structure
@@ -152,7 +153,7 @@ static void __init idp_init(void)
 static void __init idp_init_irq(void)
 {
 
-       pxa_init_irq();
+       pxa25x_init_irq();
 
        set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
 }
index 4619d5fe606c2bad027ee2bf023f6c045d3ab882..4b867b0789d54c8a9e463e08fbce0cf1f239db61 100644 (file)
 
 static void pxa_mask_low_irq(unsigned int irq)
 {
-       ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
+       ICMR &= ~(1 << irq);
 }
 
 static void pxa_unmask_low_irq(unsigned int irq)
 {
-       ICMR |= (1 << (irq + PXA_IRQ_SKIP));
+       ICMR |= (1 << irq);
 }
 
 static int pxa_set_wake(unsigned int irq, unsigned int on)
@@ -67,7 +67,27 @@ static struct irq_chip pxa_internal_chip_low = {
        .set_wake       = pxa_set_wake,
 };
 
-#if PXA_INTERNAL_IRQS > 32
+void __init pxa_init_irq_low(void)
+{
+       int irq;
+
+       /* disable all IRQs */
+       ICMR = 0;
+
+       /* all IRQs are IRQ, not FIQ */
+       ICLR = 0;
+
+       /* only unmasked interrupts kick us out of idle */
+       ICCR = 1;
+
+       for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) {
+               set_irq_chip(irq, &pxa_internal_chip_low);
+               set_irq_handler(irq, handle_level_irq);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+}
+
+#ifdef CONFIG_PXA27x
 
 /*
  * This is for the second set of internal IRQs as found on the PXA27x.
@@ -75,12 +95,12 @@ static struct irq_chip pxa_internal_chip_low = {
 
 static void pxa_mask_high_irq(unsigned int irq)
 {
-       ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP));
+       ICMR2 &= ~(1 << (irq - 32));
 }
 
 static void pxa_unmask_high_irq(unsigned int irq)
 {
-       ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
+       ICMR2 |= (1 << (irq - 32));
 }
 
 static struct irq_chip pxa_internal_chip_high = {
@@ -90,6 +110,19 @@ static struct irq_chip pxa_internal_chip_high = {
        .unmask         = pxa_unmask_high_irq,
 };
 
+void __init pxa_init_irq_high(void)
+{
+       int irq;
+
+       ICMR2 = 0;
+       ICLR2 = 0;
+
+       for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) {
+               set_irq_chip(irq, &pxa_internal_chip_high);
+               set_irq_handler(irq, handle_level_irq);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+}
 #endif
 
 /* Note that if an input/irq line ever gets changed to an output during
@@ -217,7 +250,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
        do {
                loop = 0;
 
-               mask = GEDR0 & ~3;
+               mask = GEDR0 & GPIO_IRQ_mask[0] & ~3;
                if (mask) {
                        GEDR0 = mask;
                        irq = IRQ_GPIO(2);
@@ -233,7 +266,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
                        loop = 1;
                }
 
-               mask = GEDR1;
+               mask = GEDR1 & GPIO_IRQ_mask[1];
                if (mask) {
                        GEDR1 = mask;
                        irq = IRQ_GPIO(32);
@@ -248,7 +281,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
                        loop = 1;
                }
 
-               mask = GEDR2;
+               mask = GEDR2 & GPIO_IRQ_mask[2];
                if (mask) {
                        GEDR2 = mask;
                        irq = IRQ_GPIO(64);
@@ -263,8 +296,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
                        loop = 1;
                }
 
-#if PXA_LAST_GPIO >= 96
-               mask = GEDR3;
+               mask = GEDR3 & GPIO_IRQ_mask[3];
                if (mask) {
                        GEDR3 = mask;
                        irq = IRQ_GPIO(96);
@@ -278,7 +310,6 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
                        } while (mask);
                        loop = 1;
                }
-#endif
        } while (loop);
 }
 
@@ -314,64 +345,27 @@ static struct irq_chip pxa_muxed_gpio_chip = {
        .set_wake       = pxa_set_gpio_wake,
 };
 
-
-void __init pxa_init_irq(void)
+void __init pxa_init_irq_gpio(int gpio_nr)
 {
-       int irq;
-
-       /* disable all IRQs */
-       ICMR = 0;
-
-       /* all IRQs are IRQ, not FIQ */
-       ICLR = 0;
+       int irq, i;
 
        /* clear all GPIO edge detects */
-       GFER0 = 0;
-       GFER1 = 0;
-       GFER2 = 0;
-       GRER0 = 0;
-       GRER1 = 0;
-       GRER2 = 0;
-       GEDR0 = GEDR0;
-       GEDR1 = GEDR1;
-       GEDR2 = GEDR2;
-
-#ifdef CONFIG_PXA27x
-       /* And similarly for the extra regs on the PXA27x */
-       ICMR2 = 0;
-       ICLR2 = 0;
-       GFER3 = 0;
-       GRER3 = 0;
-       GEDR3 = GEDR3;
-#endif
-
-       /* only unmasked interrupts kick us out of idle */
-       ICCR = 1;
+       for (i = 0; i < gpio_nr; i += 32) {
+               GFER(i) = 0;
+               GRER(i) = 0;
+               GEDR(i) = GEDR(i);
+       }
 
        /* GPIO 0 and 1 must have their mask bit always set */
        GPIO_IRQ_mask[0] = 3;
 
-       for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
-               set_irq_chip(irq, &pxa_internal_chip_low);
-               set_irq_handler(irq, handle_level_irq);
-               set_irq_flags(irq, IRQF_VALID);
-       }
-
-#if PXA_INTERNAL_IRQS > 32
-       for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
-               set_irq_chip(irq, &pxa_internal_chip_high);
-               set_irq_handler(irq, handle_level_irq);
-               set_irq_flags(irq, IRQF_VALID);
-       }
-#endif
-
        for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
                set_irq_chip(irq, &pxa_low_gpio_chip);
                set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
-       for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) {
+       for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(gpio_nr); irq++) {
                set_irq_chip(irq, &pxa_muxed_gpio_chip);
                set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
index e3097664ffe136e9cdb2f1386ca5174797030f3a..26116440a7c927648d7b8a3e493bdf042cab3beb 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 static unsigned int lpd270_irq_enabled;
@@ -97,7 +98,7 @@ static void __init lpd270_init_irq(void)
 {
        int irq;
 
-       pxa_init_irq();
+       pxa27x_init_irq();
 
        __raw_writew(0, LPD270_INT_MASK);
        __raw_writew(0, LPD270_INT_STATUS);
index 6377b2e29ff07df44eca47f01fd8e283baa8717f..e70048fd00a53e28f08667a4331aad4c0258ea28 100644 (file)
@@ -48,6 +48,7 @@
 #include <asm/arch/mmc.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 #define LUB_MISC_WR            __LUB_REG(LUBBOCK_FPGA_PHYS + 0x080)
@@ -103,7 +104,7 @@ static void __init lubbock_init_irq(void)
 {
        int irq;
 
-       pxa_init_irq();
+       pxa25x_init_irq();
 
        /* setup extra lubbock irqs */
        for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
index ed99a81b98f3e563905caba6db9283cd876ab2d9..b02c79c7e6a3c7d7bf972d0d200eae6e680bee63 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 static unsigned long mainstone_irq_enabled;
@@ -89,7 +90,7 @@ static void __init mainstone_init_irq(void)
 {
        int irq;
 
-       pxa_init_irq();
+       pxa27x_init_irq();
 
        /* setup extra Mainstone irqs */
        for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
index 6bf15ae73848efc667689d28661944e00a84d167..e66dbc26add1f1f8291e4461b3b2f9a000e86d3c 100644 (file)
@@ -77,7 +77,6 @@ int pxa_pm_enter(suspend_state_t state)
 {
        unsigned long sleep_save[SLEEP_SAVE_SIZE];
        unsigned long checksum = 0;
-       struct timespec delta, rtc;
        int i;
        extern void pxa_cpu_pm_enter(suspend_state_t state);
 
@@ -87,11 +86,6 @@ int pxa_pm_enter(suspend_state_t state)
                iwmmxt_task_disable(NULL);
 #endif
 
-       /* preserve current time */
-       rtc.tv_sec = RCNR;
-       rtc.tv_nsec = 0;
-       save_time_delta(&delta, &rtc);
-
        SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
        SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
        SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
@@ -183,10 +177,6 @@ int pxa_pm_enter(suspend_state_t state)
 
        RESTORE(PSTR);
 
-       /* restore current time */
-       rtc.tv_sec = RCNR;
-       restore_time_delta(&delta, &rtc);
-
 #ifdef DEBUG
        printk(KERN_DEBUG "*** made it back from resume\n");
 #endif
@@ -200,40 +190,3 @@ unsigned long sleep_phys_sp(void *sp)
 {
        return virt_to_phys(sp);
 }
-
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-int pxa_pm_prepare(suspend_state_t state)
-{
-       extern int pxa_cpu_pm_prepare(suspend_state_t state);
-
-       return pxa_cpu_pm_prepare(state);
-}
-
-EXPORT_SYMBOL_GPL(pxa_pm_prepare);
-
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-int pxa_pm_finish(suspend_state_t state)
-{
-       return 0;
-}
-
-EXPORT_SYMBOL_GPL(pxa_pm_finish);
-
-static struct pm_ops pxa_pm_ops = {
-       .prepare        = pxa_pm_prepare,
-       .enter          = pxa_pm_enter,
-       .finish         = pxa_pm_finish,
-       .valid          = pm_valid_only_mem,
-};
-
-static int __init pxa_pm_init(void)
-{
-       pm_set_ops(&pxa_pm_ops);
-       return 0;
-}
-
-device_initcall(pxa_pm_init);
index 34fb80b37023090147e43c1870591f6a829f6758..655668d4d0e9936a0eb925fa1b8d292ecde31a0f 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/mach/sharpsl_param.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 static struct resource poodle_scoop_resources[] = {
@@ -412,7 +413,7 @@ MACHINE_START(POODLE, "SHARP Poodle")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_poodle,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = poodle_init,
 MACHINE_END
index c1f21739bf714a435dc7b3df21c3fc2c488e152b..f36ca448338e380ff76cef2764193a7d83e4949c 100644 (file)
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/pm.h>
 
 #include <asm/hardware.h>
+#include <asm/arch/irqs.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/dma.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /*
  * Various clock factors driven by the CCCR register.
@@ -105,18 +110,6 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
 
 #ifdef CONFIG_PM
 
-int pxa_cpu_pm_prepare(suspend_state_t state)
-{
-       switch (state) {
-       case PM_SUSPEND_MEM:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 void pxa_cpu_pm_enter(suspend_state_t state)
 {
        extern void pxa_cpu_suspend(unsigned int);
@@ -133,4 +126,49 @@ void pxa_cpu_pm_enter(suspend_state_t state)
        }
 }
 
+static struct pm_ops pxa25x_pm_ops = {
+       .enter          = pxa_pm_enter,
+       .valid          = pm_valid_only_mem,
+};
+#endif
+
+void __init pxa25x_init_irq(void)
+{
+       pxa_init_irq_low();
+       pxa_init_irq_gpio(85);
+}
+
+static struct platform_device *pxa25x_devices[] __initdata = {
+       &pxamci_device,
+       &pxaudc_device,
+       &pxafb_device,
+       &ffuart_device,
+       &btuart_device,
+       &stuart_device,
+       &pxai2c_device,
+       &pxai2s_device,
+       &pxaficp_device,
+       &pxartc_device,
+};
+
+static int __init pxa25x_init(void)
+{
+       int ret = 0;
+
+       if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
+               if ((ret = pxa_init_dma(16)))
+                       return ret;
+#ifdef CONFIG_PM
+               pm_set_ops(&pxa25x_pm_ops);
 #endif
+               ret = platform_add_devices(pxa25x_devices,
+                                          ARRAY_SIZE(pxa25x_devices));
+       }
+       /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
+       if (cpu_is_pxa25x())
+               ret = platform_device_register(&hwuart_device);
+
+       return ret;
+}
+
+subsys_initcall(pxa25x_init);
index 1939acc3f9f7f6cdbd21e9d4fbc07ed55230686a..aa5bb02c897bd331c59ce29b1bcbc10c2be83e81 100644 (file)
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/arch/irqs.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/ohci.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/dma.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /* Crystal clock: 13MHz */
 #define BASE_CLK       13000000
@@ -122,17 +126,6 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
 
 #ifdef CONFIG_PM
 
-int pxa_cpu_pm_prepare(suspend_state_t state)
-{
-       switch (state) {
-       case PM_SUSPEND_MEM:
-       case PM_SUSPEND_STANDBY:
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
 void pxa_cpu_pm_enter(suspend_state_t state)
 {
        extern void pxa_cpu_standby(void);
@@ -162,6 +155,15 @@ void pxa_cpu_pm_enter(suspend_state_t state)
        }
 }
 
+static int pxa27x_pm_valid(suspend_state_t state)
+{
+       return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
+}
+
+static struct pm_ops pxa27x_pm_ops = {
+       .enter          = pxa_pm_enter,
+       .valid          = pxa27x_pm_valid,
+};
 #endif
 
 /*
@@ -183,7 +185,7 @@ static struct resource pxa27x_ohci_resources[] = {
        },
 };
 
-static struct platform_device ohci_device = {
+static struct platform_device pxaohci_device = {
        .name           = "pxa27x-ohci",
        .id             = -1,
        .dev            = {
@@ -196,16 +198,62 @@ static struct platform_device ohci_device = {
 
 void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
 {
-       ohci_device.dev.platform_data = info;
+       pxaohci_device.dev.platform_data = info;
 }
 
+static struct resource i2c_power_resources[] = {
+       {
+               .start  = 0x40f00180,
+               .end    = 0x40f001a3,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_PWRI2C,
+               .end    = IRQ_PWRI2C,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device pxai2c_power_device = {
+       .name           = "pxa2xx-i2c",
+       .id             = 1,
+       .resource       = i2c_power_resources,
+       .num_resources  = ARRAY_SIZE(i2c_power_resources),
+};
+
 static struct platform_device *devices[] __initdata = {
-       &ohci_device,
+       &pxamci_device,
+       &pxaudc_device,
+       &pxafb_device,
+       &ffuart_device,
+       &btuart_device,
+       &stuart_device,
+       &pxai2c_device,
+       &pxai2c_power_device,
+       &pxai2s_device,
+       &pxaficp_device,
+       &pxartc_device,
+       &pxaohci_device,
 };
 
+void __init pxa27x_init_irq(void)
+{
+       pxa_init_irq_low();
+       pxa_init_irq_high();
+       pxa_init_irq_gpio(128);
+}
+
 static int __init pxa27x_init(void)
 {
-       return platform_add_devices(devices, ARRAY_SIZE(devices));
+       int ret = 0;
+       if (cpu_is_pxa27x()) {
+               if ((ret = pxa_init_dma(32)))
+                       return ret;
+#ifdef CONFIG_PM
+               pm_set_ops(&pxa27x_pm_ops);
+#endif
+               ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+       }
+       return ret;
 }
 
 subsys_initcall(pxa27x_init);
index 3cbac63bed3c0b952db4c2af7149da2f6926c07d..bae47e145de83e01eefaf1b6fd2b05a0265f6f7a 100644 (file)
@@ -48,6 +48,7 @@
 #include <asm/hardware/scoop.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 /*
@@ -560,7 +561,7 @@ MACHINE_START(SPITZ, "SHARP Spitz")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_spitz,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa27x_init_irq,
        .init_machine   = spitz_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -572,7 +573,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_spitz,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa27x_init_irq,
        .init_machine   = spitz_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -584,7 +585,7 @@ MACHINE_START(AKITA, "SHARP Akita")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_spitz,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa27x_init_irq,
        .init_machine   = akita_init,
        .timer          = &pxa_timer,
 MACHINE_END
index 5248abe334d23f6966ea63f2c0a8462f69878261..6f91fd2d061ab0b9dc5062d5db3c551e03f6198e 100644 (file)
 #include <asm/arch/pxa-regs.h>
 
 
-static inline unsigned long pxa_get_rtc_time(void)
-{
-       return RCNR;
-}
-
 static int pxa_set_rtc(void)
 {
        unsigned long current_time = xtime.tv_sec;
@@ -122,10 +117,6 @@ static void __init pxa_timer_init(void)
 
        set_rtc = pxa_set_rtc;
 
-       tv.tv_nsec = 0;
-       tv.tv_sec = pxa_get_rtc_time();
-       do_settimeofday(&tv);
-
        OIER = 0;               /* disable any timer interrupts */
        OSSR = 0xf;             /* clear status on all timers */
        setup_irq(IRQ_OST0, &pxa_timer_irq);
index 72738771fb57cbf05495fa784f80c50215c52f92..240fd042083da10e6639f36c2b33dec5c2b8f895 100644 (file)
@@ -42,7 +42,7 @@
 #include <asm/mach/sharpsl_param.h>
 
 #include "generic.h"
-
+#include "devices.h"
 
 /*
  * SCOOP Device
@@ -332,7 +332,7 @@ MACHINE_START(TOSA, "SHARP Tosa")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_tosa,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa25x_init_irq,
        .init_machine   = tosa_init,
        .timer          = &pxa_timer,
 MACHINE_END
index 28c79bd0a3a0da9c7fd741c24534e3cf62fc7e4c..e4ba43bdf85d9756123e13bd105b1024ef42a240 100644 (file)
@@ -49,6 +49,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /********************************************************************************************
  * ONBOARD FLASH
@@ -503,7 +504,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
        .boot_params    = TRIZEPS4_SDRAM_BASE + 0x100,
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
 MACHINE_END
 
index f01de807b72fd0c30f4d42dc297cf39cb207d779..8b52ea95d4f68523f72782aee1c8ca368a7ddb35 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/platform_device.h>
 #include <linux/dm9000.h>
 
+#include <net/ax88796.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -409,6 +411,61 @@ static struct s3c2410_platform_i2c bast_i2c_info = {
        .max_freq       = 130*1000,
 };
 
+/* Asix AX88796 10/100 ethernet controller */
+
+static struct ax_plat_data bast_asix_platdata = {
+       .flags          = AXFLG_MAC_FROMDEV,
+       .wordlength     = 2,
+       .dcr_val        = 0x48,
+       .rcr_val        = 0x40,
+};
+
+static struct resource bast_asix_resource[] = {
+       [0] = {
+               .start = S3C2410_CS5 + BAST_PA_ASIXNET,
+               .end   = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20) - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
+               .end   = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
+               .flags = IORESOURCE_MEM,
+       },
+       [2] = {
+               .start = IRQ_ASIX,
+               .end   = IRQ_ASIX,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct platform_device bast_device_asix = {
+       .name           = "ax88796",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(bast_asix_resource),
+       .resource       = bast_asix_resource,
+       .dev            = {
+               .platform_data = &bast_asix_platdata
+       }
+};
+
+/* Asix AX88796 10/100 ethernet controller parallel port */
+
+static struct resource bast_asixpp_resource[] = {
+       [0] = {
+               .start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20),
+               .end   = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1b * 0x20) - 1,
+               .flags = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device bast_device_axpp = {
+       .name           = "ax88796-pp",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(bast_asixpp_resource),
+       .resource       = bast_asixpp_resource,
+};
+
+/* LCD/VGA controller */
 
 static struct s3c2410fb_mach_info __initdata bast_lcd_info = {
        .width          = 640,
@@ -453,6 +510,8 @@ static struct platform_device *bast_devices[] __initdata = {
        &s3c_device_nand,
        &bast_device_nor,
        &bast_device_dm9k,
+       &bast_device_asix,
+       &bast_device_axpp,
        &bast_sio,
 };
 
index bff7ddd06a5288e7ed764c5fcef27444142c03dc..29c163d300d4cc9f78a4f35654e3559b92497efc 100644 (file)
@@ -18,6 +18,9 @@
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 
+#include <linux/sm501.h>
+#include <linux/sm501-regs.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -42,6 +45,8 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
+#include <net/ax88796.h>
+
 #include <asm/plat-s3c24xx/clock.h>
 #include <asm/plat-s3c24xx/devs.h>
 #include <asm/plat-s3c24xx/cpu.h>
@@ -153,6 +158,29 @@ static struct mtd_partition anubis_default_nand_part[] = {
        }
 };
 
+static struct mtd_partition anubis_default_nand_part_large[] = {
+       [0] = {
+               .name   = "Boot Agent",
+               .size   = SZ_128K,
+               .offset = 0,
+       },
+       [1] = {
+               .name   = "/boot",
+               .size   = SZ_4M - SZ_128K,
+               .offset = SZ_128K,
+       },
+       [2] = {
+               .name   = "user1",
+               .offset = SZ_4M,
+               .size   = SZ_32M - SZ_4M,
+       },
+       [3] = {
+               .name   = "user2",
+               .offset = SZ_32M,
+               .size   = MTDPART_SIZ_FULL,
+       }
+};
+
 /* the Anubis has 3 selectable slots for nand-flash, the two
  * on-board chip areas, as well as the external slot.
  *
@@ -260,6 +288,104 @@ static struct platform_device anubis_device_ide1 = {
        .resource       = anubis_ide1_resource,
 };
 
+/* Asix AX88796 10/100 ethernet controller */
+
+static struct ax_plat_data anubis_asix_platdata = {
+       .flags          = AXFLG_MAC_FROMDEV,
+       .wordlength     = 2,
+       .dcr_val        = 0x48,
+       .rcr_val        = 0x40,
+};
+
+static struct resource anubis_asix_resource[] = {
+       [0] = {
+               .start = S3C2410_CS5,
+               .end   = S3C2410_CS5 + (0x20 * 0x20) -1,
+               .flags = IORESOURCE_MEM
+       },
+       [1] = {
+               .start = IRQ_ASIX,
+               .end   = IRQ_ASIX,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct platform_device anubis_device_asix = {
+       .name           = "ax88796",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(anubis_asix_resource),
+       .resource       = anubis_asix_resource,
+       .dev            = {
+               .platform_data = &anubis_asix_platdata,
+       }
+};
+
+/* SM501 */
+
+static struct resource anubis_sm501_resource[] = {
+       [0] = {
+               .start  = S3C2410_CS2,
+               .end    = S3C2410_CS2 + SZ_8M,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = S3C2410_CS2 + SZ_64M - SZ_2M,
+               .end    = S3C2410_CS2 + SZ_64M - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [2] = {
+               .start  = IRQ_EINT0,
+               .end    = IRQ_EINT0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct sm501_initdata anubis_sm501_initdata = {
+       .gpio_high      = {
+               .set    = 0x3F000000,           /* 24bit panel */
+               .mask   = 0x0,
+       },
+       .misc_timing    = {
+               .set    = 0x010100,             /* SDRAM timing */
+               .mask   = 0x1F1F00,
+       },
+       .misc_control   = {
+               .set    = SM501_MISC_PNL_24BIT,
+               .mask   = 0,
+       },
+
+       /* set the SDRAM and bus clocks */
+       .mclk           = 72 * MHZ,
+       .m1xclk         = 144 * MHZ,
+};
+
+static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = {
+       [0] = {
+               .pin_scl        = 44,
+               .pin_sda        = 45,
+       },
+       [1] = {
+               .pin_scl        = 40,
+               .pin_sda        = 41,
+       },
+};
+
+static struct sm501_platdata anubis_sm501_platdata = {
+       .init           = &anubis_sm501_initdata,
+       .gpio_i2c       = anubis_sm501_gpio_i2c,
+       .gpio_i2c_nr    = ARRAY_SIZE(anubis_sm501_gpio_i2c),
+};
+
+static struct platform_device anubis_device_sm501 = {
+       .name           = "sm501",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(anubis_sm501_resource),
+       .resource       = anubis_sm501_resource,
+       .dev            = {
+               .platform_data = &anubis_sm501_platdata,
+       },
+};
+
 /* Standard Anubis devices */
 
 static struct platform_device *anubis_devices[] __initdata = {
@@ -271,6 +397,8 @@ static struct platform_device *anubis_devices[] __initdata = {
        &s3c_device_nand,
        &anubis_device_ide0,
        &anubis_device_ide1,
+       &anubis_device_asix,
+       &anubis_device_sm501,
 };
 
 static struct clk *anubis_clocks[] = {
@@ -304,8 +432,17 @@ static void __init anubis_map_io(void)
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
 
-       /* ensure that the GPIO is setup */
-       s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+       /* check for the newer revision boards with large page nand */
+
+       if ((__raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK) >= 4) {
+               printk(KERN_INFO "ANUBIS-B detected (revision %d)\n",
+                      __raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK);
+               anubis_nand_sets[0].partitions = anubis_default_nand_part_large;
+               anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large);
+       } else {
+               /* ensure that the GPIO is setup */
+               s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+       }
 }
 
 static void __init anubis_init(void)
index 15811601f03db435a5cb7f54db6ee88a340876c4..89f4c9c5777b324ca4f603f4fdeb5ed6dabb2473 100644 (file)
@@ -166,6 +166,29 @@ static struct mtd_partition osiris_default_nand_part[] = {
        }
 };
 
+static struct mtd_partition osiris_default_nand_part_large[] = {
+       [0] = {
+               .name   = "Boot Agent",
+               .size   = SZ_128K,
+               .offset = 0,
+       },
+       [1] = {
+               .name   = "/boot",
+               .size   = SZ_4M - SZ_128K,
+               .offset = SZ_128K,
+       },
+       [2] = {
+               .name   = "user1",
+               .offset = SZ_4M,
+               .size   = SZ_32M - SZ_4M,
+       },
+       [3] = {
+               .name   = "user2",
+               .offset = SZ_32M,
+               .size   = MTDPART_SIZ_FULL,
+       }
+};
+
 /* the Osiris has 3 selectable slots for nand-flash, the two
  * on-board chip areas, as well as the external slot.
  *
@@ -322,14 +345,23 @@ static void __init osiris_map_io(void)
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
 
+       /* check for the newer revision boards with large page nand */
+
+       if ((__raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK) >= 4) {
+               printk(KERN_INFO "OSIRIS-B detected (revision %d)\n",
+                      __raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK);
+               osiris_nand_sets[0].partitions = osiris_default_nand_part_large;
+               osiris_nand_sets[0].nr_partitions = ARRAY_SIZE(osiris_default_nand_part_large);
+       } else {
+               /* write-protect line to the NAND */
+               s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+       }
+
        /* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
 
        local_irq_save(flags);
        __raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON);
        local_irq_restore(flags);
-
-       /* write-protect line to the NAND */
-       s3c2410_gpio_setpin(S3C2410_GPA0, 1);
 }
 
 static void __init osiris_init(void)
index 4cbf9468f654c970b226262c7e1d4a481436f9c5..3a0a1ee2542d05535c860f3d0cadb78e0a9a736d 100644 (file)
@@ -185,28 +185,21 @@ static int __devinit neponset_probe(struct platform_device *dev)
 /*
  * LDM power management.
  */
+static unsigned int neponset_saved_state;
+
 static int neponset_suspend(struct platform_device *dev, pm_message_t state)
 {
        /*
         * Save state.
         */
-       if (!dev->dev.power.saved_state)
-               dev->dev.power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
-       if (!dev->dev.power.saved_state)
-               return -ENOMEM;
-
-       *(unsigned int *)dev->dev.power.saved_state = NCR_0;
+       neponset_saved_state = NCR_0;
 
        return 0;
 }
 
 static int neponset_resume(struct platform_device *dev)
 {
-       if (dev->dev.power.saved_state) {
-               NCR_0 = *(unsigned int *)dev->dev.power.saved_state;
-               kfree(dev->dev.power.saved_state);
-               dev->dev.power.saved_state = NULL;
-       }
+       NCR_0 = neponset_saved_state;
 
        return 0;
 }
index d674cf3431567c88bdf5181ef99a7ab17c04fb36..01a37d3c0727de0c631dcbcd5e9c5378433c2946 100644 (file)
@@ -57,12 +57,7 @@ enum {       SLEEP_SAVE_SP = 0,
 static int sa11x0_pm_enter(suspend_state_t state)
 {
        unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
-       struct timespec delta, rtc;
 
-       /* preserve current time */
-       rtc.tv_sec = RCNR;
-       rtc.tv_nsec = 0;
-       save_time_delta(&delta, &rtc);
        gpio = GPLR;
 
        /* save vital registers */
@@ -119,10 +114,6 @@ static int sa11x0_pm_enter(suspend_state_t state)
         */
        PSSR = PSSR_PH;
 
-       /* restore current time */
-       rtc.tv_sec = RCNR;
-       restore_time_delta(&delta, &rtc);
-
        return 0;
 }
 
index 29cb0c1604ab896c719c86be3b147cbf1b1a737d..fdf7b016e7adeadfa5652ae9779803209eba3d91 100644 (file)
 #define RTC_DEF_DIVIDER                (32768 - 1)
 #define RTC_DEF_TRIM            0
 
-static unsigned long __init sa1100_get_rtc_time(void)
-{
-       /*
-        * According to the manual we should be able to let RTTR be zero
-        * and then a default divisor for a 32.768KHz clock is used.
-        * Apparently this doesn't work, at least for my SA1110 rev 5.
-        * If the clock divider is uninitialized then reset it to the
-        * default value to get the 1Hz clock.
-        */
-       if (RTTR == 0) {
-               RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-               printk(KERN_WARNING "Warning: uninitialized Real Time Clock\n");
-               /* The current RTC value probably doesn't make sense either */
-               RCNR = 0;
-               return 0;
-       }
-       return RCNR;
-}
-
 static int sa1100_set_rtc(void)
 {
        unsigned long current_time = xtime.tv_sec;
@@ -117,15 +98,10 @@ static struct irqaction sa1100_timer_irq = {
 
 static void __init sa1100_timer_init(void)
 {
-       struct timespec tv;
        unsigned long flags;
 
        set_rtc = sa1100_set_rtc;
 
-       tv.tv_nsec = 0;
-       tv.tv_sec = sa1100_get_rtc_time();
-       do_settimeofday(&tv);
-
        OIER = 0;               /* disable any timer interrupts */
        OSSR = 0xf;             /* clear status on all timers */
        setup_irq(IRQ_OST0, &sa1100_timer_irq);
index f3ade18862aaa8fd8e63488bc3eee36253c4e0f7..75952779ce1991f68114dcbeef6a188c4c47d027 100644 (file)
@@ -280,7 +280,10 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
        if (!type)
                return NULL;
 
-       size = PAGE_ALIGN(size);
+       /*
+        * Page align the mapping size, taking account of any offset.
+        */
+       size = PAGE_ALIGN(offset + size);
 
        area = get_vm_area(size, VM_IOREMAP);
        if (!area)
@@ -325,11 +328,6 @@ __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
        if (!size || last_addr < phys_addr)
                return NULL;
 
-       /*
-        * Page align the mapping size
-        */
-       size = PAGE_ALIGN(last_addr + 1) - phys_addr;
-
        return __arm_ioremap_pfn(pfn, offset, size, mtype);
 }
 EXPORT_SYMBOL(__arm_ioremap);
index 4d2b1da3cd82e6105fcc1269d71b82cf7488d265..36bff03259594a90f6e57ae54dfa7b3cce47cdfc 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_ARCH_IOP32X) += setup.o
 obj-$(CONFIG_ARCH_IOP32X) += time.o
 obj-$(CONFIG_ARCH_IOP32X) += io.o
 obj-$(CONFIG_ARCH_IOP32X) += cp6.o
+obj-$(CONFIG_ARCH_IOP32X) += adma.o
 
 # IOP33X
 obj-$(CONFIG_ARCH_IOP33X) += gpio.o
@@ -21,6 +22,7 @@ obj-$(CONFIG_ARCH_IOP33X) += setup.o
 obj-$(CONFIG_ARCH_IOP33X) += time.o
 obj-$(CONFIG_ARCH_IOP33X) += io.o
 obj-$(CONFIG_ARCH_IOP33X) += cp6.o
+obj-$(CONFIG_ARCH_IOP33X) += adma.o
 
 # IOP13XX
 obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
diff --git a/arch/arm/plat-iop/adma.c b/arch/arm/plat-iop/adma.c
new file mode 100644 (file)
index 0000000..53c5e9a
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * platform device definitions for the iop3xx dma/xor engines
+ * Copyright Â© 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/platform_device.h>
+#include <asm/hardware/iop3xx.h>
+#include <linux/dma-mapping.h>
+#include <asm/arch/adma.h>
+#include <asm/hardware/iop_adma.h>
+
+#ifdef CONFIG_ARCH_IOP32X
+#define IRQ_DMA0_EOT IRQ_IOP32X_DMA0_EOT
+#define IRQ_DMA0_EOC IRQ_IOP32X_DMA0_EOC
+#define IRQ_DMA0_ERR IRQ_IOP32X_DMA0_ERR
+
+#define IRQ_DMA1_EOT IRQ_IOP32X_DMA1_EOT
+#define IRQ_DMA1_EOC IRQ_IOP32X_DMA1_EOC
+#define IRQ_DMA1_ERR IRQ_IOP32X_DMA1_ERR
+
+#define IRQ_AA_EOT IRQ_IOP32X_AA_EOT
+#define IRQ_AA_EOC IRQ_IOP32X_AA_EOC
+#define IRQ_AA_ERR IRQ_IOP32X_AA_ERR
+#endif
+#ifdef CONFIG_ARCH_IOP33X
+#define IRQ_DMA0_EOT IRQ_IOP33X_DMA0_EOT
+#define IRQ_DMA0_EOC IRQ_IOP33X_DMA0_EOC
+#define IRQ_DMA0_ERR IRQ_IOP33X_DMA0_ERR
+
+#define IRQ_DMA1_EOT IRQ_IOP33X_DMA1_EOT
+#define IRQ_DMA1_EOC IRQ_IOP33X_DMA1_EOC
+#define IRQ_DMA1_ERR IRQ_IOP33X_DMA1_ERR
+
+#define IRQ_AA_EOT IRQ_IOP33X_AA_EOT
+#define IRQ_AA_EOC IRQ_IOP33X_AA_EOC
+#define IRQ_AA_ERR IRQ_IOP33X_AA_ERR
+#endif
+/* AAU and DMA Channels */
+static struct resource iop3xx_dma_0_resources[] = {
+       [0] = {
+               .start = IOP3XX_DMA_PHYS_BASE(0),
+               .end = IOP3XX_DMA_UPPER_PA(0),
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_DMA0_EOT,
+               .end = IRQ_DMA0_EOT,
+               .flags = IORESOURCE_IRQ
+       },
+       [2] = {
+               .start = IRQ_DMA0_EOC,
+               .end = IRQ_DMA0_EOC,
+               .flags = IORESOURCE_IRQ
+       },
+       [3] = {
+               .start = IRQ_DMA0_ERR,
+               .end = IRQ_DMA0_ERR,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct resource iop3xx_dma_1_resources[] = {
+       [0] = {
+               .start = IOP3XX_DMA_PHYS_BASE(1),
+               .end = IOP3XX_DMA_UPPER_PA(1),
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_DMA1_EOT,
+               .end = IRQ_DMA1_EOT,
+               .flags = IORESOURCE_IRQ
+       },
+       [2] = {
+               .start = IRQ_DMA1_EOC,
+               .end = IRQ_DMA1_EOC,
+               .flags = IORESOURCE_IRQ
+       },
+       [3] = {
+               .start = IRQ_DMA1_ERR,
+               .end = IRQ_DMA1_ERR,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+
+static struct resource iop3xx_aau_resources[] = {
+       [0] = {
+               .start = IOP3XX_AAU_PHYS_BASE,
+               .end = IOP3XX_AAU_UPPER_PA,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_AA_EOT,
+               .end = IRQ_AA_EOT,
+               .flags = IORESOURCE_IRQ
+       },
+       [2] = {
+               .start = IRQ_AA_EOC,
+               .end = IRQ_AA_EOC,
+               .flags = IORESOURCE_IRQ
+       },
+       [3] = {
+               .start = IRQ_AA_ERR,
+               .end = IRQ_AA_ERR,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static u64 iop3xx_adma_dmamask = DMA_32BIT_MASK;
+
+static struct iop_adma_platform_data iop3xx_dma_0_data = {
+       .hw_id = DMA0_ID,
+       .pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop3xx_dma_1_data = {
+       .hw_id = DMA1_ID,
+       .pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop3xx_aau_data = {
+       .hw_id = AAU_ID,
+       .pool_size = 3 * PAGE_SIZE,
+};
+
+struct platform_device iop3xx_dma_0_channel = {
+       .name = "iop-adma",
+       .id = 0,
+       .num_resources = 4,
+       .resource = iop3xx_dma_0_resources,
+       .dev = {
+               .dma_mask = &iop3xx_adma_dmamask,
+               .coherent_dma_mask = DMA_64BIT_MASK,
+               .platform_data = (void *) &iop3xx_dma_0_data,
+       },
+};
+
+struct platform_device iop3xx_dma_1_channel = {
+       .name = "iop-adma",
+       .id = 1,
+       .num_resources = 4,
+       .resource = iop3xx_dma_1_resources,
+       .dev = {
+               .dma_mask = &iop3xx_adma_dmamask,
+               .coherent_dma_mask = DMA_64BIT_MASK,
+               .platform_data = (void *) &iop3xx_dma_1_data,
+       },
+};
+
+struct platform_device iop3xx_aau_channel = {
+       .name = "iop-adma",
+       .id = 2,
+       .num_resources = 4,
+       .resource = iop3xx_aau_resources,
+       .dev = {
+               .dma_mask = &iop3xx_adma_dmamask,
+               .coherent_dma_mask = DMA_64BIT_MASK,
+               .platform_data = (void *) &iop3xx_aau_data,
+       },
+};
+
+static int __init iop3xx_adma_cap_init(void)
+{
+       #ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
+       dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
+       dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
+       #else
+       dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
+       dma_cap_set(DMA_MEMCPY_CRC32C, iop3xx_dma_0_data.cap_mask);
+       dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
+       #endif
+
+       #ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
+       dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
+       dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
+       #else
+       dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
+       dma_cap_set(DMA_MEMCPY_CRC32C, iop3xx_dma_1_data.cap_mask);
+       dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
+       #endif
+
+       #ifdef CONFIG_ARCH_IOP32X /* the 32x AAU does not perform zero sum */
+       dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
+       dma_cap_set(DMA_MEMSET, iop3xx_aau_data.cap_mask);
+       dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
+       #else
+       dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
+       dma_cap_set(DMA_ZERO_SUM, iop3xx_aau_data.cap_mask);
+       dma_cap_set(DMA_MEMSET, iop3xx_aau_data.cap_mask);
+       dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
+       #endif
+
+       return 0;
+}
+
+arch_initcall(iop3xx_adma_cap_init);
index d98bafcaca59a3a88b47ad3dbde222f67ae18982..017defaa525b2b8981889437824df7ae4220c246 100644 (file)
@@ -71,6 +71,7 @@ config GENERIC_CALIBRATE_DELAY
 
 config IRQCHIP_DEMUX_GPIO
        bool
+       depends on (BF53x || BF561 || BF54x)
        default y
 
 source "init/Kconfig"
@@ -114,6 +115,26 @@ config BF537
        help
          BF537 Processor Support.
 
+config BF542
+       bool "BF542"
+       help
+         BF542 Processor Support.
+
+config BF544
+       bool "BF544"
+       help
+         BF544 Processor Support.
+
+config BF548
+       bool "BF548"
+       help
+         BF548 Processor Support.
+
+config BF549
+       bool "BF549"
+       help
+         BF549 Processor Support.
+
 config BF561
        bool "BF561"
        help
@@ -125,6 +146,11 @@ choice
        prompt "Silicon Rev"
        default BF_REV_0_2 if BF537
        default BF_REV_0_3 if BF533
+       default BF_REV_0_0 if BF549
+
+config BF_REV_0_0
+       bool "0.0"
+       depends on (BF549)
 
 config BF_REV_0_2
        bool "0.2"
@@ -150,6 +176,16 @@ config BF_REV_NONE
 
 endchoice
 
+config BF53x
+       bool
+       depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537)
+       default y
+
+config BF54x
+       bool
+       depends on (BF542 || BF544 || BF548 || BF549)
+       default y
+
 config BFIN_DUAL_CORE
        bool
        depends on (BF561)
@@ -198,6 +234,12 @@ config BFIN537_BLUETECHNIX_CM
        help
          CM-BF537 support for EVAL- and DEV-Board.
 
+config BFIN548_EZKIT
+       bool "BF548-EZKIT"
+       depends on (BF548 || BF549)
+         help
+         BFIN548-EZKIT board Support.
+
 config BFIN561_BLUETECHNIX_CM
        bool "Bluetechnix CM-BF561"
        depends on (BF561)
@@ -265,6 +307,7 @@ config BFIN_SHARED_FLASH_ENET
 source "arch/blackfin/mach-bf533/Kconfig"
 source "arch/blackfin/mach-bf561/Kconfig"
 source "arch/blackfin/mach-bf537/Kconfig"
+source "arch/blackfin/mach-bf548/Kconfig"
 
 menu "Board customizations"
 
@@ -497,7 +540,8 @@ config IP_CHECKSUM_L1
 
 config CACHELINE_ALIGNED_L1
        bool "Locate cacheline_aligned data to L1 Data Memory"
-       default y
+       default y if !BF54x
+       default n if BF54x
        depends on !BF531
        help
          If enabled cacheline_anligned data is linked
@@ -541,9 +585,17 @@ endchoice
 
 source "mm/Kconfig"
 
+config LARGE_ALLOCS
+       bool "Allow allocating large blocks (> 1MB) of memory"
+       help
+         Allow the slab memory allocator to keep chains for very large
+         memory sizes - upto 32MB. You may need this if your system has
+         a lot of RAM, and you need to able to allocate very large
+         contiguous chunks. If unsure, say N.
+
 config BFIN_DMA_5XX
        bool "Enable DMA Support"
-       depends on (BF533 || BF532 || BF531 || BF537 || BF536 || BF534 || BF561)
+       depends on (BF533 || BF532 || BF531 || BF537 || BF536 || BF534 || BF561 || BF54x)
        default y
        help
          DMA driver for BF5xx.
@@ -686,6 +738,7 @@ config C_AMCKEN
 
 config C_CDPRIO
        bool "DMA has priority over core for ext. accesses"
+       depends on !BF54x
        default n
 
 config C_B0PEN
@@ -839,7 +892,7 @@ endchoice
 
 endmenu
 
-if (BF537 || BF533)
+if (BF537 || BF533 || BF54x)
 
 menu "CPU Frequency scaling"
 
index 6971a4418dfe5886083427c07031fc1e554d5f28..1b75672dfc8f8800484463b326f623d6b8bde412 100644 (file)
@@ -24,6 +24,8 @@ machine-$(CONFIG_BF533) := bf533
 machine-$(CONFIG_BF534) := bf537
 machine-$(CONFIG_BF536) := bf537
 machine-$(CONFIG_BF537) := bf537
+machine-$(CONFIG_BF548) := bf548
+machine-$(CONFIG_BF549) := bf548
 machine-$(CONFIG_BF561) := bf561
 MACHINE := $(machine-y)
 export MACHINE
index 49e8098d4c212b7635e30e86070bc4fa151d357e..8cd33560e8179922b34f454ffddcdc8e911d24cb 100644 (file)
@@ -13,7 +13,8 @@ extra-y += vmlinux.bin vmlinux.gz
 
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(ARCH) -O linux -T kernel \
-                   -C gzip -a $(CONFIG_BOOT_LOAD) -e $(CONFIG_BOOT_LOAD) -n 'Linux-$(KERNELRELEASE)' \
+                   -C gzip -n 'Linux-$(KERNELRELEASE)' -a $(CONFIG_BOOT_LOAD) \
+                   -e $(shell $(NM) vmlinux | awk '$$NF == "__start" {print $$1}') \
                    -d $< $@
 
 $(obj)/vmlinux.bin: vmlinux FORCE
diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
new file mode 100644 (file)
index 0000000..ac8390f
--- /dev/null
@@ -0,0 +1,1100 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21.5
+#
+# 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_BFIN=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_TIME is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_IRQCHIP_DEMUX_GPIO=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+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_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# 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_BF548 is not set
+CONFIG_BF549=y
+# CONFIG_BF561 is not set
+CONFIG_BF_REV_0_0=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_BF54x=y
+CONFIG_BFIN_SINGLE_CORE=y
+# CONFIG_BFIN533_EZKIT is not set
+# CONFIG_BFIN533_STAMP is not set
+# CONFIG_BFIN537_STAMP is not set
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+CONFIG_BFIN548_EZKIT=y
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
+# CONFIG_PNAV10 is not set
+# CONFIG_GENERIC_BOARD is not set
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_TIMER0=11
+CONFIG_IRQ_TIMER1=11
+CONFIG_IRQ_TIMER2=11
+CONFIG_IRQ_TIMER3=11
+CONFIG_IRQ_TIMER4=11
+CONFIG_IRQ_TIMER5=11
+CONFIG_IRQ_TIMER6=11
+CONFIG_IRQ_TIMER7=11
+CONFIG_IRQ_TIMER8=11
+CONFIG_IRQ_TIMER9=11
+CONFIG_IRQ_TIMER10=11
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+
+#
+# BF548 Specific Configuration
+#
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMAC0_ERR=7
+CONFIG_IRQ_EPPI0_ERR=7
+CONFIG_IRQ_SPORT0_ERR=7
+CONFIG_IRQ_SPORT1_ERR=7
+CONFIG_IRQ_SPI0_ERR=7
+CONFIG_IRQ_UART0_ERR=7
+CONFIG_IRQ_EPPI0=8
+CONFIG_IRQ_SPI0=10
+CONFIG_IRQ_PINT0=12
+CONFIG_IRQ_PINT1=12
+CONFIG_IRQ_MDMAS0=13
+CONFIG_IRQ_MDMAS1=13
+CONFIG_IRQ_WATCHDOG=13
+CONFIG_IRQ_DMAC1_ERR=7
+CONFIG_IRQ_SPORT2_ERR=7
+CONFIG_IRQ_SPORT3_ERR=7
+CONFIG_IRQ_MXVR_DATA=7
+CONFIG_IRQ_SPI1_ERR=7
+CONFIG_IRQ_SPI2_ERR=7
+CONFIG_IRQ_UART1_ERR=7
+CONFIG_IRQ_UART2_ERR=7
+CONFIG_IRQ_CAN0_ERR=7
+CONFIG_IRQ_SPORT2_RX=9
+CONFIG_IRQ_SPORT2_TX=9
+CONFIG_IRQ_SPORT3_RX=9
+CONFIG_IRQ_SPORT3_TX=9
+CONFIG_IRQ_EPPI1=9
+CONFIG_IRQ_EPPI2=9
+CONFIG_IRQ_SPI1=10
+CONFIG_IRQ_SPI2=10
+CONFIG_IRQ_ATAPI_RX=10
+CONFIG_IRQ_ATAPI_TX=10
+CONFIG_IRQ_TWI0=11
+CONFIG_IRQ_TWI1=11
+CONFIG_IRQ_CAN0_RX=11
+CONFIG_IRQ_CAN0_TX=11
+CONFIG_IRQ_MDMAS2=13
+CONFIG_IRQ_MDMAS3=13
+CONFIG_IRQ_MXVR_ERR=11
+CONFIG_IRQ_MXVR_MSG=11
+CONFIG_IRQ_MXVR_PKT=11
+CONFIG_IRQ_EPPI1_ERR=7
+CONFIG_IRQ_EPPI2_ERR=7
+CONFIG_IRQ_UART3_ERR=7
+CONFIG_IRQ_HOST_ERR=7
+CONFIG_IRQ_PIXC_ERR=7
+CONFIG_IRQ_NFC_ERR=7
+CONFIG_IRQ_ATAPI_ERR=7
+CONFIG_IRQ_CAN1_ERR=7
+CONFIG_IRQ_HS_DMA_ERR=7
+CONFIG_IRQ_PIXC_IN0=8
+CONFIG_IRQ_PIXC_IN1=8
+CONFIG_IRQ_PIXC_OUT=8
+CONFIG_IRQ_SDH=8
+CONFIG_IRQ_CNT=8
+CONFIG_IRQ_KEY=8
+CONFIG_IRQ_CAN1_RX=11
+CONFIG_IRQ_CAN1_TX=11
+CONFIG_IRQ_SDH_MASK0=11
+CONFIG_IRQ_SDH_MASK1=11
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
+CONFIG_IRQ_OTPSEC=11
+CONFIG_IRQ_PINT2=11
+CONFIG_IRQ_PINT3=11
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Board Setup
+#
+CONFIG_CLKIN_HZ=25000000
+CONFIG_MEM_SIZE=64
+CONFIG_MEM_ADD_WIDTH=10
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Timer Tick
+#
+# 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
+
+#
+# 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=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+# 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_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BLKFIN_CACHE=y
+CONFIG_BLKFIN_DCACHE=y
+# CONFIG_BLKFIN_DCACHE_BANKA is not set
+# CONFIG_BLKFIN_CACHE_LOCK is not set
+# CONFIG_BLKFIN_WB is not set
+CONFIG_BLKFIN_WT=y
+CONFIG_L1_MAX_PIECE=16
+
+#
+# Clock Settings
+#
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMBCTL 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=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0x99B3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# 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
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_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_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
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+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
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_BF5xx is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=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
+
+#
+# Misc devices
+#
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+# CONFIG_SMSC911X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_BF53X_PFBUTTONS 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_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_BF5xx_FBDMA is not set
+# 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 is not set
+CONFIG_SERIAL_BFIN_PIO=y
+# CONFIG_SERIAL_BFIN_UART0 is not set
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_BFIN_UART1_CTSRTS is not set
+# CONFIG_SERIAL_BFIN_UART2 is not set
+# CONFIG_SERIAL_BFIN_UART3 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
+
+#
+# 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
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+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
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_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
+
+#
+# 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
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# 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_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_DEBUG_HWERR=y
+# CONFIG_DEBUG_ICACHE_CHECK is not set
+# CONFIG_DEBUG_KERNEL_START is not set
+# CONFIG_DEBUG_SERIAL_EARLY_INIT is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
index f3b7d2f9d49c38b3ba4a444d21049df0958bb43e..f429ebc3a9613ff8d263a4d46cbba4cdb01aa108 100644 (file)
@@ -6,9 +6,12 @@ extra-y := init_task.o vmlinux.lds
 
 obj-y := \
        entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
-       sys_bfin.o time.o traps.o irqchip.o dma-mapping.o bfin_gpio.o \
-       flat.o
+       sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \
+       fixed_code.o cplbinit.o cacheinit.o
 
+obj-$(CONFIG_BF53x)                 += bfin_gpio.o
+obj-$(CONFIG_BF561)                 += bfin_gpio.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
index e455f4504509518c9791163fd05d20d443434735..b56b2741cdea6746c0a445408c5d40f40786fec5 100644 (file)
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
 #include <linux/hardirq.h>
-#include <asm/irq.h>
-#include <asm/thread_info.h>
+#include <linux/irq.h>
+#include <linux/thread_info.h>
 
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
 
 int main(void)
 {
index 069a896a8f260e67c7354066b6c05020811383cc..7cf02f02a1dbed0243cfda428d9768687f0ab808 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 
+#include <asm/blackfin.h>
 #include <asm/dma.h>
 #include <asm/cacheflush.h>
 
 ***************************************************************************/
 
 static struct dma_channel dma_ch[MAX_BLACKFIN_DMA_CHANNEL];
-#if defined (CONFIG_BF561)
-static struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
-       (struct dma_register *) DMA1_0_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_1_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_2_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_3_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_4_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_5_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_6_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_7_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_8_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_9_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_10_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_11_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_0_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_1_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_2_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_3_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_4_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_5_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_6_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_7_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_8_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_9_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_10_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_11_NEXT_DESC_PTR,
-       (struct dma_register *) MDMA1_D0_NEXT_DESC_PTR,
-       (struct dma_register *) MDMA1_S0_NEXT_DESC_PTR,
-       (struct dma_register *) MDMA1_D1_NEXT_DESC_PTR,
-       (struct dma_register *) MDMA1_S1_NEXT_DESC_PTR,
-       (struct dma_register *) MDMA2_D0_NEXT_DESC_PTR,
-       (struct dma_register *) MDMA2_S0_NEXT_DESC_PTR,
-       (struct dma_register *) MDMA2_D1_NEXT_DESC_PTR,
-       (struct dma_register *) MDMA2_S1_NEXT_DESC_PTR,
-       (struct dma_register *) IMDMA_D0_NEXT_DESC_PTR,
-       (struct dma_register *) IMDMA_S0_NEXT_DESC_PTR,
-       (struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
-       (struct dma_register *) IMDMA_S1_NEXT_DESC_PTR,
-};
-#else
-static struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
-       (struct dma_register *) DMA0_NEXT_DESC_PTR,
-       (struct dma_register *) DMA1_NEXT_DESC_PTR,
-       (struct dma_register *) DMA2_NEXT_DESC_PTR,
-       (struct dma_register *) DMA3_NEXT_DESC_PTR,
-       (struct dma_register *) DMA4_NEXT_DESC_PTR,
-       (struct dma_register *) DMA5_NEXT_DESC_PTR,
-       (struct dma_register *) DMA6_NEXT_DESC_PTR,
-       (struct dma_register *) DMA7_NEXT_DESC_PTR,
-#if (defined(CONFIG_BF537) || defined(CONFIG_BF534) || defined(CONFIG_BF536))
-       (struct dma_register *) DMA8_NEXT_DESC_PTR,
-       (struct dma_register *) DMA9_NEXT_DESC_PTR,
-       (struct dma_register *) DMA10_NEXT_DESC_PTR,
-       (struct dma_register *) DMA11_NEXT_DESC_PTR,
-#endif
-       (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
-       (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
-       (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
-       (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
-};
-#endif
 
 /*------------------------------------------------------------------------------
  *       Set the Buffer Clear bit in the Configuration register of specific DMA
@@ -138,149 +78,6 @@ static int __init blackfin_dma_init(void)
 
 arch_initcall(blackfin_dma_init);
 
-/*
- *     Form the channel find the irq number for that channel.
- */
-#if !defined(CONFIG_BF561)
-
-static int bf533_channel2irq(unsigned int channel)
-{
-       int ret_irq = -1;
-
-       switch (channel) {
-       case CH_PPI:
-               ret_irq = IRQ_PPI;
-               break;
-
-#if (defined(CONFIG_BF537) || defined(CONFIG_BF534) || defined(CONFIG_BF536))
-       case CH_EMAC_RX:
-               ret_irq = IRQ_MAC_RX;
-               break;
-
-       case CH_EMAC_TX:
-               ret_irq = IRQ_MAC_TX;
-               break;
-
-       case CH_UART1_RX:
-               ret_irq = IRQ_UART1_RX;
-               break;
-
-       case CH_UART1_TX:
-               ret_irq = IRQ_UART1_TX;
-               break;
-#endif
-
-       case CH_SPORT0_RX:
-               ret_irq = IRQ_SPORT0_RX;
-               break;
-
-       case CH_SPORT0_TX:
-               ret_irq = IRQ_SPORT0_TX;
-               break;
-
-       case CH_SPORT1_RX:
-               ret_irq = IRQ_SPORT1_RX;
-               break;
-
-       case CH_SPORT1_TX:
-               ret_irq = IRQ_SPORT1_TX;
-               break;
-
-       case CH_SPI:
-               ret_irq = IRQ_SPI;
-               break;
-
-       case CH_UART_RX:
-               ret_irq = IRQ_UART_RX;
-               break;
-
-       case CH_UART_TX:
-               ret_irq = IRQ_UART_TX;
-               break;
-
-       case CH_MEM_STREAM0_SRC:
-       case CH_MEM_STREAM0_DEST:
-               ret_irq = IRQ_MEM_DMA0;
-               break;
-
-       case CH_MEM_STREAM1_SRC:
-       case CH_MEM_STREAM1_DEST:
-               ret_irq = IRQ_MEM_DMA1;
-               break;
-       }
-       return ret_irq;
-}
-
-# define channel2irq(channel) bf533_channel2irq(channel)
-
-#else
-
-static int bf561_channel2irq(unsigned int channel)
-{
-       int ret_irq = -1;
-
-       switch (channel) {
-       case CH_PPI0:
-               ret_irq = IRQ_PPI0;
-               break;
-       case CH_PPI1:
-               ret_irq = IRQ_PPI1;
-               break;
-       case CH_SPORT0_RX:
-               ret_irq = IRQ_SPORT0_RX;
-               break;
-       case CH_SPORT0_TX:
-               ret_irq = IRQ_SPORT0_TX;
-               break;
-       case CH_SPORT1_RX:
-               ret_irq = IRQ_SPORT1_RX;
-               break;
-       case CH_SPORT1_TX:
-               ret_irq = IRQ_SPORT1_TX;
-               break;
-       case CH_SPI:
-               ret_irq = IRQ_SPI;
-               break;
-       case CH_UART_RX:
-               ret_irq = IRQ_UART_RX;
-               break;
-       case CH_UART_TX:
-               ret_irq = IRQ_UART_TX;
-               break;
-
-       case CH_MEM_STREAM0_SRC:
-       case CH_MEM_STREAM0_DEST:
-               ret_irq = IRQ_MEM_DMA0;
-               break;
-       case CH_MEM_STREAM1_SRC:
-       case CH_MEM_STREAM1_DEST:
-               ret_irq = IRQ_MEM_DMA1;
-               break;
-       case CH_MEM_STREAM2_SRC:
-       case CH_MEM_STREAM2_DEST:
-               ret_irq = IRQ_MEM_DMA2;
-               break;
-       case CH_MEM_STREAM3_SRC:
-       case CH_MEM_STREAM3_DEST:
-               ret_irq = IRQ_MEM_DMA3;
-               break;
-
-       case CH_IMEM_STREAM0_SRC:
-       case CH_IMEM_STREAM0_DEST:
-               ret_irq = IRQ_IMEM_DMA0;
-               break;
-       case CH_IMEM_STREAM1_SRC:
-       case CH_IMEM_STREAM1_DEST:
-               ret_irq = IRQ_IMEM_DMA1;
-               break;
-       }
-       return ret_irq;
-}
-
-# define channel2irq(channel) bf561_channel2irq(channel)
-
-#endif
-
 /*------------------------------------------------------------------------------
  *     Request the specific DMA channel from the system.
  *-----------------------------------------------------------------------------*/
@@ -535,7 +332,7 @@ set_bfin_dma_config(char direction, char flow_mode,
 }
 EXPORT_SYMBOL(set_bfin_dma_config);
 
-void set_dma_sg(unsigned int channel, struct dmasg * sg, int nr_sg)
+void set_dma_sg(unsigned int channel, struct dmasg *sg, int nr_sg)
 {
        BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
               && channel < MAX_BLACKFIN_DMA_CHANNEL));
@@ -604,7 +401,7 @@ static void *__dma_memcpy(void *dest, const void *src, size_t size)
 
        if (size <= 0)
                return NULL;
-       
+
        local_irq_save(flags);
 
        if ((unsigned long)src < memory_end)
@@ -748,7 +545,6 @@ void *dma_memcpy(void *dest, const void *src, size_t size)
        addr = __dma_memcpy(dest+bulk, src+bulk, rest);
        return addr;
 }
-
 EXPORT_SYMBOL(dma_memcpy);
 
 void *safe_dma_memcpy(void *dest, const void *src, size_t size)
@@ -761,14 +557,13 @@ EXPORT_SYMBOL(safe_dma_memcpy);
 
 void dma_outsb(void __iomem *addr, const void *buf, unsigned short len)
 {
-
        unsigned long flags;
-       
+
        local_irq_save(flags);
-       
-       blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
 
-       bfin_write_MDMA_D0_START_ADDR(addr);
+       blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+       bfin_write_MDMA_D0_START_ADDR(addr);
        bfin_write_MDMA_D0_X_COUNT(len);
        bfin_write_MDMA_D0_X_MODIFY(0);
        bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
@@ -796,9 +591,9 @@ EXPORT_SYMBOL(dma_outsb);
 void dma_insb(const void __iomem *addr, void *buf, unsigned short len)
 {
        unsigned long flags;
-               
+
        local_irq_save(flags);
-       bfin_write_MDMA_D0_START_ADDR(buf);
+       bfin_write_MDMA_D0_START_ADDR(buf);
        bfin_write_MDMA_D0_X_COUNT(len);
        bfin_write_MDMA_D0_X_MODIFY(1);
        bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
@@ -827,12 +622,12 @@ EXPORT_SYMBOL(dma_insb);
 void dma_outsw(void __iomem *addr, const void  *buf, unsigned short len)
 {
        unsigned long flags;
-       
+
        local_irq_save(flags);
-               
-       blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
 
-       bfin_write_MDMA_D0_START_ADDR(addr);
+       blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+       bfin_write_MDMA_D0_START_ADDR(addr);
        bfin_write_MDMA_D0_X_COUNT(len);
        bfin_write_MDMA_D0_X_MODIFY(0);
        bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
@@ -859,10 +654,10 @@ EXPORT_SYMBOL(dma_outsw);
 void dma_insw(const void __iomem *addr, void *buf, unsigned short len)
 {
        unsigned long flags;
-               
+
        local_irq_save(flags);
-       
-       bfin_write_MDMA_D0_START_ADDR(buf);
+
+       bfin_write_MDMA_D0_START_ADDR(buf);
        bfin_write_MDMA_D0_X_COUNT(len);
        bfin_write_MDMA_D0_X_MODIFY(2);
        bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
@@ -891,12 +686,12 @@ EXPORT_SYMBOL(dma_insw);
 void dma_outsl(void __iomem *addr, const void *buf, unsigned short len)
 {
        unsigned long flags;
-       
+
        local_irq_save(flags);
-       
-       blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
 
-       bfin_write_MDMA_D0_START_ADDR(addr);
+       blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+       bfin_write_MDMA_D0_START_ADDR(addr);
        bfin_write_MDMA_D0_X_COUNT(len);
        bfin_write_MDMA_D0_X_MODIFY(0);
        bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
@@ -923,10 +718,10 @@ EXPORT_SYMBOL(dma_outsl);
 void dma_insl(const void __iomem *addr, void *buf, unsigned short len)
 {
        unsigned long flags;
-       
+
        local_irq_save(flags);
-       
-       bfin_write_MDMA_D0_START_ADDR(buf);
+
+       bfin_write_MDMA_D0_START_ADDR(buf);
        bfin_write_MDMA_D0_X_COUNT(len);
        bfin_write_MDMA_D0_X_MODIFY(4);
        bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
index bb1f4fb2467c119251d2b14417998500f6de4827..bafcfa52142ba0731f5caf3ecc71e672d7678285 100644 (file)
@@ -162,7 +162,7 @@ static void port_setup(unsigned short gpio, unsigned short usage)
 
 static void default_gpio(unsigned short gpio)
 {
-       unsigned short bank,bitmask;
+       unsigned short bank, bitmask;
 
        bank = gpio_bank(gpio);
        bitmask = gpio_bit(gpio);
@@ -183,7 +183,7 @@ static int __init bfin_gpio_init(void)
 
        printk(KERN_INFO "Blackfin GPIO Controller\n");
 
-       for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE)
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE)
                reserved_map[gpio_bank(i)] = 0;
 
 #if defined(BF537_FAMILY) && (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
@@ -478,7 +478,7 @@ u32 gpio_pm_setup(void)
        u32 sic_iwr = 0;
        u16 bank, mask, i, gpio;
 
-       for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE) {
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
                mask = wakeup_map[gpio_bank(i)];
                bank = gpio_bank(i);
 
@@ -522,12 +522,11 @@ u32 gpio_pm_setup(void)
                return IWR_ENABLE_ALL;
 }
 
-
 void gpio_pm_restore(void)
 {
        u16 bank, mask, i;
 
-       for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE) {
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
                mask = wakeup_map[gpio_bank(i)];
                bank = gpio_bank(i);
 
@@ -591,7 +590,6 @@ int gpio_request(unsigned short gpio, const char *label)
 }
 EXPORT_SYMBOL(gpio_request);
 
-
 void gpio_free(unsigned short gpio)
 {
        unsigned long flags;
@@ -616,7 +614,6 @@ void gpio_free(unsigned short gpio)
 }
 EXPORT_SYMBOL(gpio_free);
 
-
 void gpio_direction_input(unsigned short gpio)
 {
        unsigned long flags;
index f64ecb638fab1a8b7d9169e317b8cdc3dc5cb947..70455949cfd207f91475d100d6f8787574b37ab2 100644 (file)
  */
 
 #include <linux/module.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
+#include <linux/uaccess.h>
+
 #include <asm/checksum.h>
 #include <asm/cacheflush.h>
-#include <asm/uaccess.h>
 
 /* platform dependent support */
 
diff --git a/arch/blackfin/kernel/cacheinit.c b/arch/blackfin/kernel/cacheinit.c
new file mode 100644 (file)
index 0000000..4d41a40
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/cpu.h>
+
+#include <asm/cacheflush.h>
+#include <asm/blackfin.h>
+#include <asm/cplbinit.h>
+
+#if defined(CONFIG_BLKFIN_CACHE)
+void bfin_icache_init(void)
+{
+       unsigned long *table = icplb_table;
+       unsigned long ctrl;
+       int i;
+
+       for (i = 0; i < MAX_CPLBS; i++) {
+               unsigned long addr = *table++;
+               unsigned long data = *table++;
+               if (addr == (unsigned long)-1)
+                       break;
+               bfin_write32(ICPLB_ADDR0 + i * 4, addr);
+               bfin_write32(ICPLB_DATA0 + i * 4, data);
+       }
+       ctrl = bfin_read_IMEM_CONTROL();
+       ctrl |= IMC | ENICPLB;
+       bfin_write_IMEM_CONTROL(ctrl);
+}
+#endif
+
+#if defined(CONFIG_BLKFIN_DCACHE)
+void bfin_dcache_init(void)
+{
+       unsigned long *table = dcplb_table;
+       unsigned long ctrl;
+       int i;
+
+       for (i = 0; i < MAX_CPLBS; i++) {
+               unsigned long addr = *table++;
+               unsigned long data = *table++;
+               if (addr == (unsigned long)-1)
+                       break;
+               bfin_write32(DCPLB_ADDR0 + i * 4, addr);
+               bfin_write32(DCPLB_DATA0 + i * 4, data);
+       }
+       ctrl = bfin_read_DMEM_CONTROL();
+       ctrl |= DMEM_CNTR;
+       bfin_write_DMEM_CONTROL(ctrl);
+}
+#endif
diff --git a/arch/blackfin/kernel/cplbinit.c b/arch/blackfin/kernel/cplbinit.c
new file mode 100644 (file)
index 0000000..bbdb403
--- /dev/null
@@ -0,0 +1,433 @@
+/*
+ * Blackfin CPLB initialization
+ *
+ *               Copyright 2004-2007 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/module.h>
+
+#include <asm/blackfin.h>
+#include <asm/cplbinit.h>
+
+u_long icplb_table[MAX_CPLBS+1];
+u_long dcplb_table[MAX_CPLBS+1];
+
+#ifdef CONFIG_CPLB_SWITCH_TAB_L1
+u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data));
+u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data));
+
+#ifdef CONFIG_CPLB_INFO
+u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data));
+u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data));
+#endif /* CONFIG_CPLB_INFO */
+
+#else
+
+u_long ipdt_table[MAX_SWITCH_I_CPLBS+1];
+u_long dpdt_table[MAX_SWITCH_D_CPLBS+1];
+
+#ifdef CONFIG_CPLB_INFO
+u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS];
+u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS];
+#endif /* CONFIG_CPLB_INFO */
+
+#endif /*CONFIG_CPLB_SWITCH_TAB_L1*/
+
+struct s_cplb {
+       struct cplb_tab init_i;
+       struct cplb_tab init_d;
+       struct cplb_tab switch_i;
+       struct cplb_tab switch_d;
+};
+
+#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
+static struct cplb_desc cplb_data[] = {
+       {
+               .start = 0,
+               .end = SIZE_1K,
+               .psize = SIZE_1K,
+               .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
+               .i_conf = SDRAM_OOPS,
+               .d_conf = SDRAM_OOPS,
+#if defined(CONFIG_DEBUG_HUNT_FOR_ZERO)
+               .valid = 1,
+#else
+               .valid = 0,
+#endif
+               .name = "ZERO Pointer Saveguard",
+       },
+       {
+               .start = L1_CODE_START,
+               .end = L1_CODE_START + L1_CODE_LENGTH,
+               .psize = SIZE_4M,
+               .attr = INITIAL_T | SWITCH_T | I_CPLB,
+               .i_conf = L1_IMEMORY,
+               .d_conf = 0,
+               .valid = 1,
+               .name = "L1 I-Memory",
+       },
+       {
+               .start = L1_DATA_A_START,
+               .end = L1_DATA_B_START + L1_DATA_B_LENGTH,
+               .psize = SIZE_4M,
+               .attr = INITIAL_T | SWITCH_T | D_CPLB,
+               .i_conf = 0,
+               .d_conf = L1_DMEMORY,
+#if ((L1_DATA_A_LENGTH > 0) || (L1_DATA_B_LENGTH > 0))
+               .valid = 1,
+#else
+               .valid = 0,
+#endif
+               .name = "L1 D-Memory",
+       },
+       {
+               .start = 0,
+               .end = 0,  /* dynamic */
+               .psize = 0,
+               .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
+               .i_conf =  SDRAM_IGENERIC,
+               .d_conf =  SDRAM_DGENERIC,
+               .valid = 1,
+               .name = "SDRAM Kernel",
+       },
+       {
+               .start = 0, /* dynamic */
+               .end = 0, /* dynamic */
+               .psize = 0,
+               .attr = INITIAL_T | SWITCH_T | D_CPLB,
+               .i_conf =  SDRAM_IGENERIC,
+               .d_conf =  SDRAM_DNON_CHBL,
+               .valid = 1,
+               .name = "SDRAM RAM MTD",
+       },
+       {
+               .start = 0, /* dynamic */
+               .end = 0,   /* dynamic */
+               .psize = SIZE_1M,
+               .attr = INITIAL_T | SWITCH_T | D_CPLB,
+               .d_conf = SDRAM_DNON_CHBL,
+               .valid = 1,
+               .name = "SDRAM Uncached DMA ZONE",
+       },
+       {
+               .start = 0, /* dynamic */
+               .end = 0, /* dynamic */
+               .psize = 0,
+               .attr = SWITCH_T | D_CPLB,
+               .i_conf = 0, /* dynamic */
+               .d_conf = 0, /* dynamic */
+               .valid = 1,
+               .name = "SDRAM Reserved Memory",
+       },
+       {
+               .start = ASYNC_BANK0_BASE,
+               .end = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE,
+               .psize = 0,
+               .attr = SWITCH_T | D_CPLB,
+               .d_conf = SDRAM_EBIU,
+               .valid = 1,
+               .name = "ASYNC Memory",
+       },
+       {
+#if defined(CONFIG_BF561)
+               .start = L2_SRAM,
+               .end = L2_SRAM_END,
+               .psize = SIZE_1M,
+               .attr = SWITCH_T | D_CPLB,
+               .i_conf = L2_MEMORY,
+               .d_conf = L2_MEMORY,
+               .valid = 1,
+#else
+               .valid = 0,
+#endif
+               .name = "L2 Memory",
+       }
+};
+
+static u16 __init lock_kernel_check(u32 start, u32 end)
+{
+       if ((start <= (u32) _stext && end >= (u32) _end)
+           || (start >= (u32) _stext && end <= (u32) _end))
+               return IN_KERNEL;
+       return 0;
+}
+
+static unsigned short __init
+fill_cplbtab(struct cplb_tab *table,
+            unsigned long start, unsigned long end,
+            unsigned long block_size, unsigned long cplb_data)
+{
+       int i;
+
+       switch (block_size) {
+       case SIZE_4M:
+               i = 3;
+               break;
+       case SIZE_1M:
+               i = 2;
+               break;
+       case SIZE_4K:
+               i = 1;
+               break;
+       case SIZE_1K:
+       default:
+               i = 0;
+               break;
+       }
+
+       cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
+
+       while ((start < end) && (table->pos < table->size)) {
+
+               table->tab[table->pos++] = start;
+
+               if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
+                       table->tab[table->pos++] =
+                           cplb_data | CPLB_LOCK | CPLB_DIRTY;
+               else
+                       table->tab[table->pos++] = cplb_data;
+
+               start += block_size;
+       }
+       return 0;
+}
+
+static unsigned short __init
+close_cplbtab(struct cplb_tab *table)
+{
+
+       while (table->pos < table->size) {
+
+               table->tab[table->pos++] = 0;
+               table->tab[table->pos++] = 0; /* !CPLB_VALID */
+       }
+       return 0;
+}
+
+/* helper function */
+static void __fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
+{
+       if (cplb_data[i].psize) {
+               fill_cplbtab(t,
+                               cplb_data[i].start,
+                               cplb_data[i].end,
+                               cplb_data[i].psize,
+                               cplb_data[i].i_conf);
+       } else {
+#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
+               if (i == SDRAM_KERN) {
+                       fill_cplbtab(t,
+                                       cplb_data[i].start,
+                                       cplb_data[i].end,
+                                       SIZE_4M,
+                                       cplb_data[i].i_conf);
+               } else
+#endif
+               {
+                       fill_cplbtab(t,
+                                       cplb_data[i].start,
+                                       a_start,
+                                       SIZE_1M,
+                                       cplb_data[i].i_conf);
+                       fill_cplbtab(t,
+                                       a_start,
+                                       a_end,
+                                       SIZE_4M,
+                                       cplb_data[i].i_conf);
+                       fill_cplbtab(t, a_end,
+                                       cplb_data[i].end,
+                                       SIZE_1M,
+                                       cplb_data[i].i_conf);
+               }
+       }
+}
+
+static void __fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
+{
+       if (cplb_data[i].psize) {
+               fill_cplbtab(t,
+                               cplb_data[i].start,
+                               cplb_data[i].end,
+                               cplb_data[i].psize,
+                               cplb_data[i].d_conf);
+       } else {
+               fill_cplbtab(t,
+                               cplb_data[i].start,
+                               a_start, SIZE_1M,
+                               cplb_data[i].d_conf);
+               fill_cplbtab(t, a_start,
+                               a_end, SIZE_4M,
+                               cplb_data[i].d_conf);
+               fill_cplbtab(t, a_end,
+                               cplb_data[i].end,
+                               SIZE_1M,
+                               cplb_data[i].d_conf);
+       }
+}
+
+void __init generate_cpl_tables(void)
+{
+
+       u16 i, j, process;
+       u32 a_start, a_end, as, ae, as_1m;
+
+       struct cplb_tab *t_i = NULL;
+       struct cplb_tab *t_d = NULL;
+       struct s_cplb cplb;
+
+       cplb.init_i.size = MAX_CPLBS;
+       cplb.init_d.size = MAX_CPLBS;
+       cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
+       cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
+
+       cplb.init_i.pos = 0;
+       cplb.init_d.pos = 0;
+       cplb.switch_i.pos = 0;
+       cplb.switch_d.pos = 0;
+
+       cplb.init_i.tab = icplb_table;
+       cplb.init_d.tab = dcplb_table;
+       cplb.switch_i.tab = ipdt_table;
+       cplb.switch_d.tab = dpdt_table;
+
+       cplb_data[SDRAM_KERN].end = memory_end;
+
+#ifdef CONFIG_MTD_UCLINUX
+       cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start;
+       cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size;
+       cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0;
+# if defined(CONFIG_ROMFS_FS)
+       cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB;
+
+       /*
+        * The ROMFS_FS size is often not multiple of 1MB.
+        * This can cause multiple CPLB sets covering the same memory area.
+        * This will then cause multiple CPLB hit exceptions.
+        * Workaround: We ensure a contiguous memory area by extending the kernel
+        * memory section over the mtd section.
+        * For ROMFS_FS memory must be covered with ICPLBs anyways.
+        * So there is no difference between kernel and mtd memory setup.
+        */
+
+       cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;;
+       cplb_data[SDRAM_RAM_MTD].valid = 0;
+
+# endif
+#else
+       cplb_data[SDRAM_RAM_MTD].valid = 0;
+#endif
+
+       cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION;
+       cplb_data[SDRAM_DMAZ].end = _ramend;
+
+       cplb_data[RES_MEM].start = _ramend;
+       cplb_data[RES_MEM].end = physical_mem_end;
+
+       if (reserved_mem_dcache_on)
+               cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC;
+       else
+               cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL;
+
+       if (reserved_mem_icache_on)
+               cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC;
+       else
+               cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL;
+
+       for (i = ZERO_P; i <= L2_MEM; i++) {
+               if (!cplb_data[i].valid)
+                       continue;
+
+               as_1m = cplb_data[i].start % SIZE_1M;
+
+               /* We need to make sure all sections are properly 1M aligned
+                * However between Kernel Memory and the Kernel mtd section, depending on the
+                * rootfs size, there can be overlapping memory areas.
+                */
+
+               if (as_1m && i != L1I_MEM && i != L1D_MEM) {
+#ifdef CONFIG_MTD_UCLINUX
+                       if (i == SDRAM_RAM_MTD) {
+                               if ((cplb_data[SDRAM_KERN].end + 1) > cplb_data[SDRAM_RAM_MTD].start)
+                                       cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M)) + SIZE_1M;
+                               else
+                                       cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M));
+                       } else
+#endif
+                               printk(KERN_WARNING "Unaligned Start of %s at 0x%X\n",
+                                      cplb_data[i].name, cplb_data[i].start);
+               }
+
+               as = cplb_data[i].start % SIZE_4M;
+               ae = cplb_data[i].end % SIZE_4M;
+
+               if (as)
+                       a_start = cplb_data[i].start + (SIZE_4M - (as));
+               else
+                       a_start = cplb_data[i].start;
+
+               a_end = cplb_data[i].end - ae;
+
+               for (j = INITIAL_T; j <= SWITCH_T; j++) {
+
+                       switch (j) {
+                       case INITIAL_T:
+                               if (cplb_data[i].attr & INITIAL_T) {
+                                       t_i = &cplb.init_i;
+                                       t_d = &cplb.init_d;
+                                       process = 1;
+                               } else
+                                       process = 0;
+                               break;
+                       case SWITCH_T:
+                               if (cplb_data[i].attr & SWITCH_T) {
+                                       t_i = &cplb.switch_i;
+                                       t_d = &cplb.switch_d;
+                                       process = 1;
+                               } else
+                                       process = 0;
+                               break;
+                       default:
+                                       process = 0;
+                               break;
+                       }
+
+                       if (!process)
+                               continue;
+                       if (cplb_data[i].attr & I_CPLB)
+                               __fill_code_cplbtab(t_i, i, a_start, a_end);
+
+                       if (cplb_data[i].attr & D_CPLB)
+                               __fill_data_cplbtab(t_d, i, a_start, a_end);
+               }
+       }
+
+/* close tables */
+
+       close_cplbtab(&cplb.init_i);
+       close_cplbtab(&cplb.init_d);
+
+       cplb.init_i.tab[cplb.init_i.pos] = -1;
+       cplb.init_d.tab[cplb.init_d.pos] = -1;
+       cplb.switch_i.tab[cplb.switch_i.pos] = -1;
+       cplb.switch_d.tab[cplb.switch_d.pos] = -1;
+
+}
+
+#endif
+
index 539eb24e062fbc17c3ea3e12f4b3763cb1572940..ea48d5b13f11469a18faebbd15461def98ef5d23 100644 (file)
@@ -34,8 +34,8 @@
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/io.h>
 #include <asm/cacheflush.h>
-#include <asm/io.h>
 #include <asm/bfin-global.h>
 
 static spinlock_t dma_page_lock;
@@ -159,10 +159,13 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 
        BUG_ON(direction == DMA_NONE);
 
-       for (i = 0; i < nents; i++)
-               invalidate_dcache_range(sg_dma_address(&sg[i]),
-                                       sg_dma_address(&sg[i]) +
-                                       sg_dma_len(&sg[i]));
+       for (i = 0; i < nents; i++, sg++) {
+               sg->dma_address = page_address(sg->page) + sg->offset;
+
+               invalidate_dcache_range(sg_dma_address(sg),
+                                       sg_dma_address(sg) +
+                                       sg_dma_len(sg));
+       }
 
        return nents;
 }
index 8b89c99f9dfa386ff99133773147bc60425339e0..0fcba74840b7ae157ead33a94ded8219a37c165b 100644 (file)
 #include <linux/init.h>
 #include <linux/module.h>
 
-static int *testarg = (int*)0xfeb00000;
+static int *testarg = (int *)0xfeb00000;
 
 static int test_init(void)
 {
        *testarg = 1;
-       printk("Dual core test module inserted: set testarg = [%d]\n @ [%p]\n",
+       printk(KERN_INFO "Dual core test module inserted: set testarg = [%d]\n @ [%p]\n",
               *testarg, testarg);
        return 0;
 }
 
 static void test_exit(void)
 {
-       printk("Dual core test module removed: testarg = [%d]\n", *testarg);
+       printk(KERN_INFO "Dual core test module removed: testarg = [%d]\n", *testarg);
 }
 
 module_init(test_init);
diff --git a/arch/blackfin/kernel/fixed_code.S b/arch/blackfin/kernel/fixed_code.S
new file mode 100644 (file)
index 0000000..d8b1ebc
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * This file contains sequences of code that will be copied to a
+ * fixed location, defined in <asm/atomic_seq.h>.  The interrupt
+ * handlers ensure that these sequences appear to be atomic when
+ * executed from userspace.
+ * These are aligned to 16 bytes, so that we have some space to replace
+ * these sequences with something else (e.g. kernel traps if we ever do
+ * BF561 SMP).
+ */
+#include <linux/linkage.h>
+#include <linux/unistd.h>
+#include <asm/entry.h>
+
+.text
+ENTRY(_fixed_code_start)
+
+.align 16
+ENTRY(_sigreturn_stub)
+       P0 = __NR_rt_sigreturn;
+       EXCPT 0;
+       /* Speculative execution paranoia.  */
+0:     JUMP.S 0b;
+ENDPROC (_sigreturn_stub)
+
+.align 16
+       /*
+        * Atomic swap, 8 bit.
+        * Inputs:      P0: memory address to use
+        *              R1: value to store
+        * Output:      R0: old contents of the memory address, zero extended.
+        */
+ENTRY(_atomic_xchg32)
+       R0 = [P0];
+       [P0] = R1;
+       rts;
+ENDPROC (_atomic_xchg32)
+
+.align 16
+       /*
+        * Compare and swap, 32 bit.
+        * Inputs:      P0: memory address to use
+        *              R1: compare value
+        *              R2: new value to store
+        * The new value is stored if the contents of the memory
+        * address is equal to the compare value.
+        * Output:      R0: old contents of the memory address.
+        */
+ENTRY(_atomic_cas32)
+       R0 = [P0];
+       CC = R0 == R1;
+       IF !CC JUMP 1f;
+       [P0] = R2;
+1:
+       rts;
+ENDPROC (_atomic_cas32)
+
+.align 16
+       /*
+        * Atomic add, 32 bit.
+        * Inputs:      P0: memory address to use
+        *              R0: value to add
+        * Outputs:     R0: new contents of the memory address.
+        *              R1: previous contents of the memory address.
+        */
+ENTRY(_atomic_add32)
+       R1 = [P0];
+       R0 = R1 + R0;
+       [P0] = R0;
+       rts;
+ENDPROC (_atomic_add32)
+
+.align 16
+       /*
+        * Atomic sub, 32 bit.
+        * Inputs:      P0: memory address to use
+        *              R0: value to subtract
+        * Outputs:     R0: new contents of the memory address.
+        *              R1: previous contents of the memory address.
+        */
+ENTRY(_atomic_sub32)
+       R1 = [P0];
+       R0 = R1 - R0;
+       [P0] = R0;
+       rts;
+ENDPROC (_atomic_sub32)
+
+.align 16
+       /*
+        * Atomic ior, 32 bit.
+        * Inputs:      P0: memory address to use
+        *              R0: value to ior
+        * Outputs:     R0: new contents of the memory address.
+        *              R1: previous contents of the memory address.
+        */
+ENTRY(_atomic_ior32)
+       R1 = [P0];
+       R0 = R1 | R0;
+       [P0] = R0;
+       rts;
+ENDPROC (_atomic_ior32)
+
+.align 16
+       /*
+        * Atomic ior, 32 bit.
+        * Inputs:      P0: memory address to use
+        *              R0: value to ior
+        * Outputs:     R0: new contents of the memory address.
+        *              R1: previous contents of the memory address.
+        */
+ENTRY(_atomic_and32)
+       R1 = [P0];
+       R0 = R1 & R0;
+       [P0] = R0;
+       rts;
+ENDPROC (_atomic_ior32)
+
+.align 16
+       /*
+        * Atomic ior, 32 bit.
+        * Inputs:      P0: memory address to use
+        *              R0: value to ior
+        * Outputs:     R0: new contents of the memory address.
+        *              R1: previous contents of the memory address.
+        */
+ENTRY(_atomic_xor32)
+       R1 = [P0];
+       R0 = R1 ^ R0;
+       [P0] = R0;
+       rts;
+ENDPROC (_atomic_ior32)
+
+ENTRY(_fixed_code_end)
index a92587b628b570feca2940c9e882b164797db946..d188b24305364e4e348a592a2075734a8204a7e2 100644 (file)
@@ -36,24 +36,22 @@ unsigned long bfin_get_addr_from_rp(unsigned long *ptr,
        unsigned long val;
 
        switch (type) {
-               case FLAT_BFIN_RELOC_TYPE_16_BIT:
-               case FLAT_BFIN_RELOC_TYPE_16H_BIT:
-                       usptr = (unsigned short *)ptr;
-                       pr_debug("*usptr = %x", get_unaligned(usptr));
-                       val = get_unaligned(usptr);
-                       val += *persistent;
-                       break;
+       case FLAT_BFIN_RELOC_TYPE_16_BIT:
+       case FLAT_BFIN_RELOC_TYPE_16H_BIT:
+               usptr = (unsigned short *)ptr;
+               pr_debug("*usptr = %x", get_unaligned(usptr));
+               val = get_unaligned(usptr);
+               val += *persistent;
+               break;
 
-               case FLAT_BFIN_RELOC_TYPE_32_BIT:
-                       pr_debug("*ptr = %lx", get_unaligned(ptr));
-                       val = get_unaligned(ptr);
-                       break;
+       case FLAT_BFIN_RELOC_TYPE_32_BIT:
+               pr_debug("*ptr = %lx", get_unaligned(ptr));
+               val = get_unaligned(ptr);
+               break;
 
-               default:
-                       pr_debug("BINFMT_FLAT: Unknown relocation type %x\n",
-                               type);
-
-                       return 0;
+       default:
+               pr_debug("BINFMT_FLAT: Unknown relocation type %x\n", type);
+               return 0;
        }
 
        /*
@@ -81,21 +79,20 @@ void bfin_put_addr_at_rp(unsigned long *ptr, unsigned long addr,
        int type = (relval >> 26) & 7;
 
        switch (type) {
-               case FLAT_BFIN_RELOC_TYPE_16_BIT:
-                       put_unaligned(addr, usptr);
-                       pr_debug("new value %x at %p", get_unaligned(usptr),
-                               usptr);
-                       break;
+       case FLAT_BFIN_RELOC_TYPE_16_BIT:
+               put_unaligned(addr, usptr);
+               pr_debug("new value %x at %p", get_unaligned(usptr), usptr);
+               break;
 
-               case FLAT_BFIN_RELOC_TYPE_16H_BIT:
-                       put_unaligned(addr >> 16, usptr);
-                       pr_debug("new value %x", get_unaligned(usptr));
-                       break;
+       case FLAT_BFIN_RELOC_TYPE_16H_BIT:
+               put_unaligned(addr >> 16, usptr);
+               pr_debug("new value %x", get_unaligned(usptr));
+               break;
 
-               case FLAT_BFIN_RELOC_TYPE_32_BIT:
-                       put_unaligned(addr, ptr);
-                       pr_debug("new ptr =%lx", get_unaligned(ptr));
-                       break;
+       case FLAT_BFIN_RELOC_TYPE_32_BIT:
+               put_unaligned(addr, ptr);
+               pr_debug("new ptr =%lx", get_unaligned(ptr));
+               break;
        }
 }
 EXPORT_SYMBOL(bfin_put_addr_at_rp);
index 80996a1a94ca9996edb9dccde1925c398490cd8b..1fc001c7abdac10b22be68d12b89c6be3638a69f 100644 (file)
@@ -82,7 +82,7 @@ int show_interrupts(struct seq_file *p, void *v)
                        seq_printf(p, ", %s", action->name);
 
                seq_putc(p, '\n');
            unlock:
+ unlock:
                spin_unlock_irqrestore(&irq_desc[i].lock, flags);
        } else if (i == NR_IRQS) {
                seq_printf(p, "Err: %10lu\n", irq_err_count);
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c
new file mode 100644 (file)
index 0000000..a9c1551
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * File:         arch/blackfin/kernel/kgdb.c
+ * Based on:
+ * Author:       Sonic Zhang
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:          $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $
+ *
+ * Modified:
+ *               Copyright 2005-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/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/ptrace.h>              /* for linux pt_regs struct */
+#include <linux/kgdb.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/debugger.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/blackfin.h>
+
+/* Put the error code here just in case the user cares.  */
+int gdb_bf533errcode;
+/* Likewise, the vector number here (since GDB only gets the signal
+   number through the usual means, and that's not very specific).  */
+int gdb_bf533vector = -1;
+
+#if KGDB_MAX_NO_CPUS != 8
+#error change the definition of slavecpulocks
+#endif
+
+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+       gdb_regs[BFIN_R0] = regs->r0;
+       gdb_regs[BFIN_R1] = regs->r1;
+       gdb_regs[BFIN_R2] = regs->r2;
+       gdb_regs[BFIN_R3] = regs->r3;
+       gdb_regs[BFIN_R4] = regs->r4;
+       gdb_regs[BFIN_R5] = regs->r5;
+       gdb_regs[BFIN_R6] = regs->r6;
+       gdb_regs[BFIN_R7] = regs->r7;
+       gdb_regs[BFIN_P0] = regs->p0;
+       gdb_regs[BFIN_P1] = regs->p1;
+       gdb_regs[BFIN_P2] = regs->p2;
+       gdb_regs[BFIN_P3] = regs->p3;
+       gdb_regs[BFIN_P4] = regs->p4;
+       gdb_regs[BFIN_P5] = regs->p5;
+       gdb_regs[BFIN_SP] = regs->reserved;
+       gdb_regs[BFIN_FP] = regs->fp;
+       gdb_regs[BFIN_I0] = regs->i0;
+       gdb_regs[BFIN_I1] = regs->i1;
+       gdb_regs[BFIN_I2] = regs->i2;
+       gdb_regs[BFIN_I3] = regs->i3;
+       gdb_regs[BFIN_M0] = regs->m0;
+       gdb_regs[BFIN_M1] = regs->m1;
+       gdb_regs[BFIN_M2] = regs->m2;
+       gdb_regs[BFIN_M3] = regs->m3;
+       gdb_regs[BFIN_B0] = regs->b0;
+       gdb_regs[BFIN_B1] = regs->b1;
+       gdb_regs[BFIN_B2] = regs->b2;
+       gdb_regs[BFIN_B3] = regs->b3;
+       gdb_regs[BFIN_L0] = regs->l0;
+       gdb_regs[BFIN_L1] = regs->l1;
+       gdb_regs[BFIN_L2] = regs->l2;
+       gdb_regs[BFIN_L3] = regs->l3;
+       gdb_regs[BFIN_A0_DOT_X] = regs->a0x;
+       gdb_regs[BFIN_A0_DOT_W] = regs->a0w;
+       gdb_regs[BFIN_A1_DOT_X] = regs->a1x;
+       gdb_regs[BFIN_A1_DOT_W] = regs->a1w;
+       gdb_regs[BFIN_ASTAT] = regs->astat;
+       gdb_regs[BFIN_RETS] = regs->rets;
+       gdb_regs[BFIN_LC0] = regs->lc0;
+       gdb_regs[BFIN_LT0] = regs->lt0;
+       gdb_regs[BFIN_LB0] = regs->lb0;
+       gdb_regs[BFIN_LC1] = regs->lc1;
+       gdb_regs[BFIN_LT1] = regs->lt1;
+       gdb_regs[BFIN_LB1] = regs->lb1;
+       gdb_regs[BFIN_CYCLES] = 0;
+       gdb_regs[BFIN_CYCLES2] = 0;
+       gdb_regs[BFIN_USP] = regs->usp;
+       gdb_regs[BFIN_SEQSTAT] = regs->seqstat;
+       gdb_regs[BFIN_SYSCFG] = regs->syscfg;
+       gdb_regs[BFIN_RETI] = regs->pc;
+       gdb_regs[BFIN_RETX] = regs->retx;
+       gdb_regs[BFIN_RETN] = regs->retn;
+       gdb_regs[BFIN_RETE] = regs->rete;
+       gdb_regs[BFIN_PC] = regs->pc;
+       gdb_regs[BFIN_CC] = 0;
+       gdb_regs[BFIN_EXTRA1] = 0;
+       gdb_regs[BFIN_EXTRA2] = 0;
+       gdb_regs[BFIN_EXTRA3] = 0;
+       gdb_regs[BFIN_IPEND] = regs->ipend;
+}
+
+/*
+ * Extracts ebp, esp and eip values understandable by gdb from the values
+ * saved by switch_to.
+ * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp
+ * prior to entering switch_to is 8 greater then the value that is saved.
+ * If switch_to changes, change following code appropriately.
+ */
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+{
+       gdb_regs[BFIN_SP] = p->thread.ksp;
+       gdb_regs[BFIN_PC] = p->thread.pc;
+       gdb_regs[BFIN_SEQSTAT] = p->thread.seqstat;
+}
+
+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+       regs->r0 = gdb_regs[BFIN_R0];
+       regs->r1 = gdb_regs[BFIN_R1];
+       regs->r2 = gdb_regs[BFIN_R2];
+       regs->r3 = gdb_regs[BFIN_R3];
+       regs->r4 = gdb_regs[BFIN_R4];
+       regs->r5 = gdb_regs[BFIN_R5];
+       regs->r6 = gdb_regs[BFIN_R6];
+       regs->r7 = gdb_regs[BFIN_R7];
+       regs->p0 = gdb_regs[BFIN_P0];
+       regs->p1 = gdb_regs[BFIN_P1];
+       regs->p2 = gdb_regs[BFIN_P2];
+       regs->p3 = gdb_regs[BFIN_P3];
+       regs->p4 = gdb_regs[BFIN_P4];
+       regs->p5 = gdb_regs[BFIN_P5];
+       regs->fp = gdb_regs[BFIN_FP];
+       regs->i0 = gdb_regs[BFIN_I0];
+       regs->i1 = gdb_regs[BFIN_I1];
+       regs->i2 = gdb_regs[BFIN_I2];
+       regs->i3 = gdb_regs[BFIN_I3];
+       regs->m0 = gdb_regs[BFIN_M0];
+       regs->m1 = gdb_regs[BFIN_M1];
+       regs->m2 = gdb_regs[BFIN_M2];
+       regs->m3 = gdb_regs[BFIN_M3];
+       regs->b0 = gdb_regs[BFIN_B0];
+       regs->b1 = gdb_regs[BFIN_B1];
+       regs->b2 = gdb_regs[BFIN_B2];
+       regs->b3 = gdb_regs[BFIN_B3];
+       regs->l0 = gdb_regs[BFIN_L0];
+       regs->l1 = gdb_regs[BFIN_L1];
+       regs->l2 = gdb_regs[BFIN_L2];
+       regs->l3 = gdb_regs[BFIN_L3];
+       regs->a0x = gdb_regs[BFIN_A0_DOT_X];
+       regs->a0w = gdb_regs[BFIN_A0_DOT_W];
+       regs->a1x = gdb_regs[BFIN_A1_DOT_X];
+       regs->a1w = gdb_regs[BFIN_A1_DOT_W];
+       regs->rets = gdb_regs[BFIN_RETS];
+       regs->lc0 = gdb_regs[BFIN_LC0];
+       regs->lt0 = gdb_regs[BFIN_LT0];
+       regs->lb0 = gdb_regs[BFIN_LB0];
+       regs->lc1 = gdb_regs[BFIN_LC1];
+       regs->lt1 = gdb_regs[BFIN_LT1];
+       regs->lb1 = gdb_regs[BFIN_LB1];
+       regs->usp = gdb_regs[BFIN_USP];
+       regs->syscfg = gdb_regs[BFIN_SYSCFG];
+       regs->retx = gdb_regs[BFIN_PC];
+       regs->retn = gdb_regs[BFIN_RETN];
+       regs->rete = gdb_regs[BFIN_RETE];
+       regs->pc = gdb_regs[BFIN_PC];
+
+#if 0                          /* can't change these */
+       regs->astat = gdb_regs[BFIN_ASTAT];
+       regs->seqstat = gdb_regs[BFIN_SEQSTAT];
+       regs->ipend = gdb_regs[BFIN_IPEND];
+#endif
+}
+
+struct hw_breakpoint {
+       unsigned int occupied:1;
+       unsigned int skip:1;
+       unsigned int enabled:1;
+       unsigned int type:1;
+       unsigned int dataacc:2;
+       unsigned short count;
+       unsigned int addr;
+} breakinfo[HW_BREAKPOINT_NUM];
+
+int kgdb_arch_init(void)
+{
+       kgdb_remove_all_hw_break();
+       return 0;
+}
+
+int kgdb_set_hw_break(unsigned long addr)
+{
+       int breakno;
+       for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++)
+               if (!breakinfo[breakno].occupied) {
+                       breakinfo[breakno].occupied = 1;
+                       breakinfo[breakno].enabled = 1;
+                       breakinfo[breakno].type = 1;
+                       breakinfo[breakno].addr = addr;
+                       return 0;
+               }
+
+       return -ENOSPC;
+}
+
+int kgdb_remove_hw_break(unsigned long addr)
+{
+       int breakno;
+       for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++)
+               if (breakinfo[breakno].addr == addr)
+                       memset(&(breakinfo[breakno]), 0, sizeof(struct hw_breakpoint));
+
+       return 0;
+}
+
+void kgdb_remove_all_hw_break(void)
+{
+       memset(breakinfo, 0, sizeof(struct hw_breakpoint)*8);
+}
+
+/*
+void kgdb_show_info(void)
+{
+       printk(KERN_DEBUG "hwd: wpia0=0x%x, wpiacnt0=%d, wpiactl=0x%x, wpstat=0x%x\n",
+               bfin_read_WPIA0(), bfin_read_WPIACNT0(),
+               bfin_read_WPIACTL(), bfin_read_WPSTAT());
+}
+*/
+
+void kgdb_correct_hw_break(void)
+{
+       int breakno;
+       int correctit;
+       uint32_t wpdactl = bfin_read_WPDACTL();
+
+       correctit = 0;
+       for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) {
+               if (breakinfo[breakno].type == 1) {
+                       switch (breakno) {
+                       case 0:
+                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN0)) {
+                                       correctit = 1;
+                                       wpdactl &= ~(WPIREN01|EMUSW0);
+                                       wpdactl |= WPIAEN0|WPICNTEN0;
+                                       bfin_write_WPIA0(breakinfo[breakno].addr);
+                                       bfin_write_WPIACNT0(breakinfo[breakno].skip);
+                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN0)) {
+                                       correctit = 1;
+                                       wpdactl &= ~WPIAEN0;
+                               }
+                               break;
+
+                       case 1:
+                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN1)) {
+                                       correctit = 1;
+                                       wpdactl &= ~(WPIREN01|EMUSW1);
+                                       wpdactl |= WPIAEN1|WPICNTEN1;
+                                       bfin_write_WPIA1(breakinfo[breakno].addr);
+                                       bfin_write_WPIACNT1(breakinfo[breakno].skip);
+                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN1)) {
+                                       correctit = 1;
+                                       wpdactl &= ~WPIAEN1;
+                               }
+                               break;
+
+                       case 2:
+                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN2)) {
+                                       correctit = 1;
+                                       wpdactl &= ~(WPIREN23|EMUSW2);
+                                       wpdactl |= WPIAEN2|WPICNTEN2;
+                                       bfin_write_WPIA2(breakinfo[breakno].addr);
+                                       bfin_write_WPIACNT2(breakinfo[breakno].skip);
+                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN2)) {
+                                       correctit = 1;
+                                       wpdactl &= ~WPIAEN2;
+                               }
+                               break;
+
+                       case 3:
+                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN3)) {
+                                       correctit = 1;
+                                       wpdactl &= ~(WPIREN23|EMUSW3);
+                                       wpdactl |= WPIAEN3|WPICNTEN3;
+                                       bfin_write_WPIA3(breakinfo[breakno].addr);
+                                       bfin_write_WPIACNT3(breakinfo[breakno].skip);
+                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN3)) {
+                                       correctit = 1;
+                                       wpdactl &= ~WPIAEN3;
+                               }
+                               break;
+                       case 4:
+                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN4)) {
+                                       correctit = 1;
+                                       wpdactl &= ~(WPIREN45|EMUSW4);
+                                       wpdactl |= WPIAEN4|WPICNTEN4;
+                                       bfin_write_WPIA4(breakinfo[breakno].addr);
+                                       bfin_write_WPIACNT4(breakinfo[breakno].skip);
+                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN4)) {
+                                       correctit = 1;
+                                       wpdactl &= ~WPIAEN4;
+                               }
+                               break;
+                       case 5:
+                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN5)) {
+                                       correctit = 1;
+                                       wpdactl &= ~(WPIREN45|EMUSW5);
+                                       wpdactl |= WPIAEN5|WPICNTEN5;
+                                       bfin_write_WPIA5(breakinfo[breakno].addr);
+                                       bfin_write_WPIACNT5(breakinfo[breakno].skip);
+                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN5)) {
+                                       correctit = 1;
+                                       wpdactl &= ~WPIAEN5;
+                               }
+                               break;
+                       }
+               }
+       }
+       if (correctit) {
+               wpdactl &= ~WPAND;
+               wpdactl |= WPPWR;
+               /*printk("correct_hw_break: wpdactl=0x%x\n", wpdactl);*/
+               bfin_write_WPDACTL(wpdactl);
+               CSYNC();
+               /*kgdb_show_info();*/
+       }
+}
+
+void kgdb_disable_hw_debug(struct pt_regs *regs)
+{
+       /* Disable hardware debugging while we are in kgdb */
+       bfin_write_WPIACTL(bfin_read_WPIACTL() & ~0x1);
+       CSYNC();
+}
+
+void kgdb_post_master_code(struct pt_regs *regs, int eVector, int err_code)
+{
+       /* Master processor is completely in the debugger */
+       gdb_bf533vector = eVector;
+       gdb_bf533errcode = err_code;
+}
+
+int kgdb_arch_handle_exception(int exceptionVector, int signo,
+                              int err_code, char *remcom_in_buffer,
+                              char *remcom_out_buffer,
+                              struct pt_regs *linux_regs)
+{
+       long addr;
+       long breakno;
+       char *ptr;
+       int newPC;
+       int wp_status;
+
+       switch (remcom_in_buffer[0]) {
+       case 'c':
+       case 's':
+               if (kgdb_contthread && kgdb_contthread != current) {
+                       strcpy(remcom_out_buffer, "E00");
+                       break;
+               }
+
+               kgdb_contthread = NULL;
+
+               /* try to read optional parameter, pc unchanged if no parm */
+               ptr = &remcom_in_buffer[1];
+               if (kgdb_hex2long(&ptr, &addr)) {
+                       linux_regs->retx = addr;
+               }
+               newPC = linux_regs->retx;
+
+               /* clear the trace bit */
+               linux_regs->syscfg &= 0xfffffffe;
+
+               /* set the trace bit if we're stepping */
+               if (remcom_in_buffer[0] == 's') {
+                       linux_regs->syscfg |= 0x1;
+                       debugger_step = 1;
+               }
+
+               wp_status = bfin_read_WPSTAT();
+               CSYNC();
+
+               if (exceptionVector == VEC_WATCH) {
+                       for (breakno = 0; breakno < 6; ++breakno) {
+                               if (wp_status & (1 << breakno)) {
+                                       breakinfo->skip = 1;
+                                       break;
+                               }
+                       }
+               }
+               kgdb_correct_hw_break();
+
+               bfin_write_WPSTAT(0);
+
+               return 0;
+       }                       /* switch */
+       return -1;              /* this means that we do not want to exit from the handler */
+}
+
+struct kgdb_arch arch_kgdb_ops = {
+       .gdb_bpt_instr = {0xa1},
+       .flags = KGDB_HW_BREAKPOINT,
+};
index 372f756f1ad9cf4d0d717af332b988ecd51e294d..8b9fe29d03f4f4a02c91f3a2585b703bfa7b3bc9 100644 (file)
@@ -165,8 +165,8 @@ 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))) {
+                   ((strcmp(".text", secstrings + s->sh_name) == 0) &&
+                    (hdr->e_flags & FLG_CODE_IN_L1) && (s->sh_size > 0))) {
                        mod->arch.text_l1 = s;
                        dest = l1_inst_sram_alloc(s->sh_size);
                        if (dest == NULL) {
@@ -179,9 +179,9 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
                        s->sh_flags &= ~SHF_ALLOC;
                        s->sh_addr = (unsigned long)dest;
                }
-               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))) {
+               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))) {
                        mod->arch.data_a_l1 = s;
                        dest = l1_data_sram_alloc(s->sh_size);
                        if (dest == NULL) {
@@ -195,8 +195,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
                        s->sh_addr = (unsigned long)dest;
                }
                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))) {
+                   ((strcmp(".bss", secstrings + s->sh_name) == 0) &&
+                    (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
                        mod->arch.bss_a_l1 = s;
                        dest = l1_data_sram_alloc(s->sh_size);
                        if (dest == NULL) {
@@ -326,7 +326,7 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
                        pr_debug("before %x after %x\n", *location16,
                                       (value & 0xffff));
                        tmp = (value & 0xffff);
-                       if((unsigned long)location16 >= L1_CODE_START) {
+                       if ((unsigned long)location16 >= L1_CODE_START) {
                                dma_memcpy(location16, &tmp, 2);
                        } else
                                *location16 = tmp;
@@ -335,7 +335,7 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
                        pr_debug("before %x after %x\n", *location16,
                                       ((value >> 16) & 0xffff));
                        tmp = ((value >> 16) & 0xffff);
-                       if((unsigned long)location16 >= L1_CODE_START) {
+                       if ((unsigned long)location16 >= L1_CODE_START) {
                                dma_memcpy(location16, &tmp, 2);
                        } else
                                *location16 = tmp;
@@ -404,8 +404,8 @@ 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.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)))) {
                        apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
                                           symindex, i, mod);
@@ -417,13 +417,13 @@ module_finalize(const Elf_Ehdr * hdr,
 void module_arch_cleanup(struct module *mod)
 {
        if ((mod->arch.text_l1) && (mod->arch.text_l1->sh_addr))
-               l1_inst_sram_free((void*)mod->arch.text_l1->sh_addr);
+               l1_inst_sram_free((void *)mod->arch.text_l1->sh_addr);
        if ((mod->arch.data_a_l1) && (mod->arch.data_a_l1->sh_addr))
-               l1_data_sram_free((void*)mod->arch.data_a_l1->sh_addr);
+               l1_data_sram_free((void *)mod->arch.data_a_l1->sh_addr);
        if ((mod->arch.bss_a_l1) && (mod->arch.bss_a_l1->sh_addr))
-               l1_data_sram_free((void*)mod->arch.bss_a_l1->sh_addr);
+               l1_data_sram_free((void *)mod->arch.bss_a_l1->sh_addr);
        if ((mod->arch.data_b_l1) && (mod->arch.data_b_l1->sh_addr))
-               l1_data_B_sram_free((void*)mod->arch.data_b_l1->sh_addr);
+               l1_data_B_sram_free((void *)mod->arch.data_b_l1->sh_addr);
        if ((mod->arch.bss_b_l1) && (mod->arch.bss_b_l1->sh_addr))
-               l1_data_B_sram_free((void*)mod->arch.bss_b_l1->sh_addr);
+               l1_data_B_sram_free((void *)mod->arch.bss_b_l1->sh_addr);
 }
index 3eff7439d8d3f0e3a5bd542a307491f85a96a287..5a51dd6ab28095966fac101dc229fb600934765f 100644 (file)
 #include <linux/unistd.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
+#include <linux/uaccess.h>
 
 #include <asm/blackfin.h>
-#include <asm/uaccess.h>
+#include <asm/fixed_code.h>
 
 #define        LED_ON  0
 #define        LED_OFF 1
@@ -173,8 +174,8 @@ void show_regs(struct pt_regs *regs)
        printk(KERN_NOTICE "R4: %08lx  R5: %08lx  R6: %08lx  R7: %08lx\n",
               regs->r4, regs->r5, regs->r6, regs->r7);
 
-       if (!(regs->ipend))
-               printk("USP: %08lx\n", rdusp());
+       if (!regs->ipend)
+               printk(KERN_NOTICE "USP: %08lx\n", rdusp());
 }
 
 /* Fill in the fpu structure for a core dump.  */
@@ -322,7 +323,7 @@ asmlinkage int sys_execve(char *name, char **argv, char **envp)
                goto out;
        error = do_execve(filename, argv, envp, regs);
        putname(filename);
     out:
+ out:
        unlock_kernel();
        return error;
 }
@@ -350,13 +351,77 @@ unsigned long get_wchan(struct task_struct *p)
        return 0;
 }
 
+void finish_atomic_sections (struct pt_regs *regs)
+{
+       if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END)
+               return;
+
+       switch (regs->pc) {
+       case ATOMIC_XCHG32 + 2:
+               put_user(regs->r1, (int *)regs->p0);
+               regs->pc += 2;
+               break;
+
+       case ATOMIC_CAS32 + 2:
+       case ATOMIC_CAS32 + 4:
+               if (regs->r0 == regs->r1)
+                       put_user(regs->r2, (int *)regs->p0);
+               regs->pc = ATOMIC_CAS32 + 8;
+               break;
+       case ATOMIC_CAS32 + 6:
+               put_user(regs->r2, (int *)regs->p0);
+               regs->pc += 2;
+               break;
+
+       case ATOMIC_ADD32 + 2:
+               regs->r0 = regs->r1 + regs->r0;
+               /* fall through */
+       case ATOMIC_ADD32 + 4:
+               put_user(regs->r0, (int *)regs->p0);
+               regs->pc = ATOMIC_ADD32 + 6;
+               break;
+
+       case ATOMIC_SUB32 + 2:
+               regs->r0 = regs->r1 - regs->r0;
+               /* fall through */
+       case ATOMIC_SUB32 + 4:
+               put_user(regs->r0, (int *)regs->p0);
+               regs->pc = ATOMIC_SUB32 + 6;
+               break;
+
+       case ATOMIC_IOR32 + 2:
+               regs->r0 = regs->r1 | regs->r0;
+               /* fall through */
+       case ATOMIC_IOR32 + 4:
+               put_user(regs->r0, (int *)regs->p0);
+               regs->pc = ATOMIC_IOR32 + 6;
+               break;
+
+       case ATOMIC_AND32 + 2:
+               regs->r0 = regs->r1 & regs->r0;
+               /* fall through */
+       case ATOMIC_AND32 + 4:
+               put_user(regs->r0, (int *)regs->p0);
+               regs->pc = ATOMIC_AND32 + 6;
+               break;
+
+       case ATOMIC_XOR32 + 2:
+               regs->r0 = regs->r1 ^ regs->r0;
+               /* fall through */
+       case ATOMIC_XOR32 + 4:
+               put_user(regs->r0, (int *)regs->p0);
+               regs->pc = ATOMIC_XOR32 + 6;
+               break;
+       }
+}
+
 #if defined(CONFIG_ACCESS_CHECK)
 int _access_ok(unsigned long addr, unsigned long size)
 {
 
        if (addr > (addr + size))
                return 0;
-       if (segment_eq(get_fs(),KERNEL_DS))
+       if (segment_eq(get_fs(), KERNEL_DS))
                return 1;
 #ifdef CONFIG_MTD_UCLINUX
        if (addr >= memory_start && (addr + size) <= memory_end)
index e718bb4a1ef027fdc050f51d4303cbe11a8905d0..ed800c7456dd004a9863e2643a8a4aac720d2c9b 100644 (file)
@@ -36,8 +36,8 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/signal.h>
+#include <linux/uaccess.h>
 
-#include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -122,7 +122,7 @@ static inline long get_reg(struct task_struct *task, int regno)
 static inline int
 put_reg(struct task_struct *task, int regno, unsigned long data)
 {
-       char * reg_ptr;
+       char *reg_ptr;
 
        struct pt_regs *regs =
            (struct pt_regs *)((unsigned long)task_stack_page(task) +
@@ -146,7 +146,7 @@ put_reg(struct task_struct *task, int regno, unsigned long data)
                break;
        default:
                if (regno <= 216)
-                       *(long *)(reg_ptr + regno) = data;
+                       *(long *)(reg_ptr + regno) = data;
        }
        return 0;
 }
index 83060f98d15d265cfcfbc50f657743f7e99255c4..f59dcee7bae3da76723a3432866fa08d8b7d9f0a 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/cacheflush.h>
 #include <asm/blackfin.h>
 #include <asm/cplbinit.h>
+#include <asm/fixed_code.h>
 
 u16 _bfin_swrst;
 
@@ -63,10 +64,6 @@ EXPORT_SYMBOL(mtd_size);
 
 char __initdata command_line[COMMAND_LINE_SIZE];
 
-#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
-static void generate_cpl_tables(void);
-#endif
-
 void __init bf53x_cache_init(void)
 {
 #if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
@@ -197,6 +194,17 @@ void __init setup_arch(char **cmdline_p)
        /* this give a chance to get printk() working before crash. */
 #endif
 
+       printk(KERN_INFO "Hardware Trace ");
+       if (bfin_read_TBUFCTL() & 0x1 )
+               printk("Active ");
+       else
+               printk("Off ");
+       if (bfin_read_TBUFCTL() & 0x2)
+               printk("and Enabled\n");
+       else
+       printk("and Disabled\n");
+
+
 #if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
        /* we need to initialize the Flashrom device here since we might
         * do things with flash early on in the boot
@@ -354,15 +362,15 @@ void __init setup_arch(char **cmdline_p)
               , _stext, _etext,
               __start_rodata, __end_rodata,
               _sdata, _edata,
-              (void*)&init_thread_union, (void*)((int)(&init_thread_union) + 0x2000),
+              (void *)&init_thread_union, (void *)((int)(&init_thread_union) + 0x2000),
               __init_begin, __init_end,
               __bss_start, __bss_stop,
-              (void*)_ramstart, (void*)memory_end
+              (void *)_ramstart, (void *)memory_end
 #ifdef CONFIG_MTD_UCLINUX
-              , (void*)memory_mtd_start, (void*)(memory_mtd_start + mtd_size)
+              , (void *)memory_mtd_start, (void *)(memory_mtd_start + mtd_size)
 #endif
 #if DMA_UNCACHED_REGION > 0
-              , (void*)(_ramend - DMA_UNCACHED_REGION), (void*)(_ramend)
+              , (void *)(_ramend - DMA_UNCACHED_REGION), (void *)(_ramend)
 #endif
               );
 
@@ -388,11 +396,11 @@ void __init setup_arch(char **cmdline_p)
        /* check the size of the l1 area */
        l1_length = _etext_l1 - _stext_l1;
        if (l1_length > L1_CODE_LENGTH)
-               panic("L1 memory overflow\n");
+               panic("L1 code memory overflow\n");
 
        l1_length = _ebss_l1 - _sdata_l1;
        if (l1_length > L1_DATA_A_LENGTH)
-               panic("L1 memory overflow\n");
+               panic("L1 data memory overflow\n");
 
 #ifdef BF561_FAMILY
        _bfin_swrst = bfin_read_SICA_SWRST();
@@ -400,10 +408,28 @@ void __init setup_arch(char **cmdline_p)
        _bfin_swrst = bfin_read_SWRST();
 #endif
 
-       bf53x_cache_init();
+       /* Copy atomic sequences to their fixed location, and sanity check that
+          these locations are the ones that we advertise to userspace.  */
+       memcpy((void *)FIXED_CODE_START, &fixed_code_start,
+              FIXED_CODE_END - FIXED_CODE_START);
+       BUG_ON((char *)&sigreturn_stub - (char *)&fixed_code_start
+              != SIGRETURN_STUB - FIXED_CODE_START);
+       BUG_ON((char *)&atomic_xchg32 - (char *)&fixed_code_start
+              != ATOMIC_XCHG32 - FIXED_CODE_START);
+       BUG_ON((char *)&atomic_cas32 - (char *)&fixed_code_start
+              != ATOMIC_CAS32 - FIXED_CODE_START);
+       BUG_ON((char *)&atomic_add32 - (char *)&fixed_code_start
+              != ATOMIC_ADD32 - FIXED_CODE_START);
+       BUG_ON((char *)&atomic_sub32 - (char *)&fixed_code_start
+              != ATOMIC_SUB32 - FIXED_CODE_START);
+       BUG_ON((char *)&atomic_ior32 - (char *)&fixed_code_start
+              != ATOMIC_IOR32 - FIXED_CODE_START);
+       BUG_ON((char *)&atomic_and32 - (char *)&fixed_code_start
+              != ATOMIC_AND32 - FIXED_CODE_START);
+       BUG_ON((char *)&atomic_xor32 - (char *)&fixed_code_start
+              != ATOMIC_XOR32 - FIXED_CODE_START);
 
-       printk(KERN_INFO "Hardware Trace Enabled\n");
-       bfin_write_TBUFCTL(0x03);
+       bf53x_cache_init();
 }
 
 static int __init topology_init(void)
@@ -421,286 +447,6 @@ static int __init topology_init(void)
 
 subsys_initcall(topology_init);
 
-#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
-static u16 __init lock_kernel_check(u32 start, u32 end)
-{
-       if ((start <= (u32) _stext && end >= (u32) _end)
-           || (start >= (u32) _stext && end <= (u32) _end))
-               return IN_KERNEL;
-       return 0;
-}
-
-static unsigned short __init
-fill_cplbtab(struct cplb_tab *table,
-            unsigned long start, unsigned long end,
-            unsigned long block_size, unsigned long cplb_data)
-{
-       int i;
-
-       switch (block_size) {
-       case SIZE_4M:
-               i = 3;
-               break;
-       case SIZE_1M:
-               i = 2;
-               break;
-       case SIZE_4K:
-               i = 1;
-               break;
-       case SIZE_1K:
-       default:
-               i = 0;
-               break;
-       }
-
-       cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
-
-       while ((start < end) && (table->pos < table->size)) {
-
-               table->tab[table->pos++] = start;
-
-               if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
-                       table->tab[table->pos++] =
-                           cplb_data | CPLB_LOCK | CPLB_DIRTY;
-               else
-                       table->tab[table->pos++] = cplb_data;
-
-               start += block_size;
-       }
-       return 0;
-}
-
-static unsigned short __init
-close_cplbtab(struct cplb_tab *table)
-{
-
-       while (table->pos < table->size) {
-
-               table->tab[table->pos++] = 0;
-               table->tab[table->pos++] = 0; /* !CPLB_VALID */
-       }
-       return 0;
-}
-
-/* helper function */
-static void __fill_code_cplbtab(struct cplb_tab *t, int i,
-                               u32 a_start, u32 a_end)
-{
-       if (cplb_data[i].psize) {
-               fill_cplbtab(t,
-                               cplb_data[i].start,
-                               cplb_data[i].end,
-                               cplb_data[i].psize,
-                               cplb_data[i].i_conf);
-       } else {
-#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
-               if (i == SDRAM_KERN) {
-                       fill_cplbtab(t,
-                                       cplb_data[i].start,
-                                       cplb_data[i].end,
-                                       SIZE_4M,
-                                       cplb_data[i].i_conf);
-               } else {
-#endif
-                       fill_cplbtab(t,
-                                       cplb_data[i].start,
-                                       a_start,
-                                       SIZE_1M,
-                                       cplb_data[i].i_conf);
-                       fill_cplbtab(t,
-                                       a_start,
-                                       a_end,
-                                       SIZE_4M,
-                                       cplb_data[i].i_conf);
-                       fill_cplbtab(t, a_end,
-                                       cplb_data[i].end,
-                                       SIZE_1M,
-                                       cplb_data[i].i_conf);
-               }
-       }
-}
-
-static void __fill_data_cplbtab(struct cplb_tab *t, int i,
-                               u32 a_start, u32 a_end)
-{
-       if (cplb_data[i].psize) {
-               fill_cplbtab(t,
-                               cplb_data[i].start,
-                               cplb_data[i].end,
-                               cplb_data[i].psize,
-                               cplb_data[i].d_conf);
-       } else {
-               fill_cplbtab(t,
-                               cplb_data[i].start,
-                               a_start, SIZE_1M,
-                               cplb_data[i].d_conf);
-               fill_cplbtab(t, a_start,
-                               a_end, SIZE_4M,
-                               cplb_data[i].d_conf);
-               fill_cplbtab(t, a_end,
-                               cplb_data[i].end,
-                               SIZE_1M,
-                               cplb_data[i].d_conf);
-       }
-}
-static void __init generate_cpl_tables(void)
-{
-
-       u16 i, j, process;
-       u32 a_start, a_end, as, ae, as_1m;
-
-       struct cplb_tab *t_i = NULL;
-       struct cplb_tab *t_d = NULL;
-       struct s_cplb cplb;
-
-       cplb.init_i.size = MAX_CPLBS;
-       cplb.init_d.size = MAX_CPLBS;
-       cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
-       cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
-
-       cplb.init_i.pos = 0;
-       cplb.init_d.pos = 0;
-       cplb.switch_i.pos = 0;
-       cplb.switch_d.pos = 0;
-
-       cplb.init_i.tab = icplb_table;
-       cplb.init_d.tab = dcplb_table;
-       cplb.switch_i.tab = ipdt_table;
-       cplb.switch_d.tab = dpdt_table;
-
-       cplb_data[SDRAM_KERN].end = memory_end;
-
-#ifdef CONFIG_MTD_UCLINUX
-       cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start;
-       cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size;
-       cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0;
-# if defined(CONFIG_ROMFS_FS)
-       cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB;
-
-       /*
-        * The ROMFS_FS size is often not multiple of 1MB.
-        * This can cause multiple CPLB sets covering the same memory area.
-        * This will then cause multiple CPLB hit exceptions.
-        * Workaround: We ensure a contiguous memory area by extending the kernel
-        * memory section over the mtd section.
-        * For ROMFS_FS memory must be covered with ICPLBs anyways.
-        * So there is no difference between kernel and mtd memory setup.
-        */
-
-       cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;;
-       cplb_data[SDRAM_RAM_MTD].valid = 0;
-
-# endif
-#else
-       cplb_data[SDRAM_RAM_MTD].valid = 0;
-#endif
-
-       cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION;
-       cplb_data[SDRAM_DMAZ].end = _ramend;
-
-       cplb_data[RES_MEM].start = _ramend;
-       cplb_data[RES_MEM].end = physical_mem_end;
-
-       if (reserved_mem_dcache_on)
-               cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC;
-       else
-               cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL;
-
-       if (reserved_mem_icache_on)
-               cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC;
-       else
-               cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL;
-
-       for (i = ZERO_P; i <= L2_MEM; i++) {
-               if (!cplb_data[i].valid)
-                       continue;
-
-               as_1m = cplb_data[i].start % SIZE_1M;
-
-               /*
-                * We need to make sure all sections are properly 1M aligned
-                * However between Kernel Memory and the Kernel mtd section,
-                * depending on the rootfs size, there can be overlapping
-                * memory areas.
-                */
-
-               if (as_1m && i != L1I_MEM && i != L1D_MEM) {
-#ifdef CONFIG_MTD_UCLINUX
-                       if (i == SDRAM_RAM_MTD) {
-                               if ((cplb_data[SDRAM_KERN].end + 1) >
-                                               cplb_data[SDRAM_RAM_MTD].start)
-                                       cplb_data[SDRAM_RAM_MTD].start =
-                                               (cplb_data[i].start &
-                                                (-2*SIZE_1M)) + SIZE_1M;
-                               else
-                                       cplb_data[SDRAM_RAM_MTD].start =
-                                               (cplb_data[i].start &
-                                                (-2*SIZE_1M));
-                       } else
-#endif
-                               printk(KERN_WARNING
-                                       "Unaligned Start of %s at 0x%X\n",
-                                       cplb_data[i].name, cplb_data[i].start);
-               }
-
-               as = cplb_data[i].start % SIZE_4M;
-               ae = cplb_data[i].end % SIZE_4M;
-
-               if (as)
-                       a_start = cplb_data[i].start + (SIZE_4M - (as));
-               else
-                       a_start = cplb_data[i].start;
-
-               a_end = cplb_data[i].end - ae;
-
-               for (j = INITIAL_T; j <= SWITCH_T; j++) {
-
-                       switch (j) {
-                       case INITIAL_T:
-                               if (cplb_data[i].attr & INITIAL_T) {
-                                       t_i = &cplb.init_i;
-                                       t_d = &cplb.init_d;
-                                       process = 1;
-                               } else
-                                       process = 0;
-                               break;
-                       case SWITCH_T:
-                               if (cplb_data[i].attr & SWITCH_T) {
-                                       t_i = &cplb.switch_i;
-                                       t_d = &cplb.switch_d;
-                                       process = 1;
-                               } else
-                                       process = 0;
-                               break;
-                       default:
-                                       process = 0;
-                               break;
-                       }
-
-                       if (!process)
-                               continue;
-                       if (cplb_data[i].attr & I_CPLB)
-                               __fill_code_cplbtab(t_i, i, a_start, a_end);
-
-                       if (cplb_data[i].attr & D_CPLB)
-                               __fill_data_cplbtab(t_d, i, a_start, a_end);
-               }
-       }
-
-/* close tables */
-
-       close_cplbtab(&cplb.init_i);
-       close_cplbtab(&cplb.init_d);
-
-       cplb.init_i.tab[cplb.init_i.pos] = -1;
-       cplb.init_d.tab[cplb.init_d.pos] = -1;
-       cplb.switch_i.tab[cplb.switch_i.pos] = -1;
-       cplb.switch_d.tab[cplb.switch_d.pos] = -1;
-
-}
-
-#endif
-
 static u_long get_vco(void)
 {
        u_long msel;
@@ -730,7 +476,6 @@ u_long get_cclk(void)
                return get_vco() / ssel;
        return get_vco() >> csel;
 }
-
 EXPORT_SYMBOL(get_cclk);
 
 /* Get the System clock */
@@ -749,7 +494,6 @@ u_long get_sclk(void)
 
        return get_vco() / ssel;
 }
-
 EXPORT_SYMBOL(get_sclk);
 
 /*
@@ -804,23 +548,23 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                seq_printf(m, "D-CACHE:\tOFF\n");
 
 
-       switch(bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) {
-               case ACACHE_BSRAM:
-                       seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n");
-                       dcache_size = 16;
-                       dsup_banks = 1;
-                       break;
-               case ACACHE_BCACHE:
-                       seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n");
-                       dcache_size = 32;
-                       dsup_banks = 2;
-                       break;
-               case ASRAM_BSRAM:
-                       seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n");
-                       dcache_size = 0;
-                       dsup_banks = 0;
-                       break;
-               default:
+       switch (bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) {
+       case ACACHE_BSRAM:
+               seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n");
+               dcache_size = 16;
+               dsup_banks = 1;
+               break;
+       case ACACHE_BCACHE:
+               seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n");
+               dcache_size = 32;
+               dsup_banks = 2;
+               break;
+       case ASRAM_BSRAM:
+               seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n");
+               dcache_size = 0;
+               dsup_banks = 0;
+               break;
+       default:
                break;
        }
 
index 316e65c3439d48cb084facd9783ed217928a73e4..5564c9588aa807bd3c0384c9b5256e205b1cd7bd 100644 (file)
@@ -34,8 +34,8 @@
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 #include <linux/freezer.h>
+#include <linux/uaccess.h>
 
-#include <asm/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
 
@@ -124,7 +124,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
 
        return r0;
 
     badframe:
+ badframe:
        force_sig(SIGSEGV, current);
        return 0;
 }
@@ -239,7 +239,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
 
        return 0;
 
     give_sigsegv:
+ give_sigsegv:
        if (sig == SIGSEGV)
                ka->sa.sa_handler = SIG_DFL;
        force_sig(SIGSEGV, current);
@@ -263,7 +263,7 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
                }
                /* fallthrough */
        case -ERESTARTNOINTR:
            do_restart:
+ do_restart:
                regs->p0 = regs->orig_p0;
                regs->r0 = regs->orig_r0;
                regs->pc -= 2;
@@ -341,7 +341,7 @@ asmlinkage void do_signal(struct pt_regs *regs)
                return;
        }
 
-no_signal:
+ no_signal:
        /* Did we come from a system call? */
        if (regs->orig_p0 >= 0)
                /* Restart the system call - no handlers present */
index f436e6743f5a0f60b657f22f08991e015e69d36e..f5e1ae3d1705958dceb302addac289613e489120 100644 (file)
 #include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/file.h>
+#include <linux/uaccess.h>
+#include <linux/ipc.h>
+#include <linux/unistd.h>
 
 #include <asm/cacheflush.h>
-#include <asm/uaccess.h>
-#include <asm/ipc.h>
 #include <asm/dma.h>
-#include <asm/unistd.h>
 
 /*
  * sys_pipe() is the normal C calling standard for creating
@@ -83,7 +83,7 @@ do_mmap2(unsigned long addr, unsigned long len,
 
        if (file)
                fput(file);
     out:
+ out:
        return error;
 }
 
index f578176b6d9240080aca1dc5061e92878635b9e1..beef057bd1dc74d0451acec312c7657cfd21ebf3 100644 (file)
@@ -87,7 +87,7 @@ void __init init_leds(void)
 static inline void do_leds(void)
 {
        static unsigned int count = 50;
-       static int flag = 0;
+       static int flag;
        unsigned short tmp = 0;
 
        if (--count == 0) {
@@ -200,7 +200,7 @@ irqreturn_t timer_interrupt(int irq, void *dummy)__attribute__((l1_text));
 irqreturn_t timer_interrupt(int irq, void *dummy)
 {
        /* last time the cmos clock got updated */
-       static long last_rtc_update = 0;
+       static long last_rtc_update;
 
        write_seqlock(&xtime_lock);
 
index 56058b0b6d4a604954938c5f1964e4e58d2f66cc..3909f5b3553679ac1b6215b95e31f856aa34b2dd 100644 (file)
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
 #include <asm/traps.h>
 #include <asm/cacheflush.h>
 #include <asm/blackfin.h>
-#include <asm/uaccess.h>
 #include <asm/irq_handler.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/kallsyms.h>
+#include <asm/trace.h>
 
 #ifdef CONFIG_KGDB
 # include <linux/debugger.h>
@@ -76,7 +76,7 @@ static int printk_address(unsigned long address)
                if (!modname)
                        modname = delim = "";
                return printk("<0x%p> { %s%s%s%s + 0x%lx }",
-                             (void*)address, delim, modname, delim, symname,
+                             (void *)address, delim, modname, delim, symname,
                              (unsigned long)offset);
 
        }
@@ -119,7 +119,7 @@ static int printk_address(unsigned long address)
 
                                write_unlock_irq(&tasklist_lock);
                                return printk("<0x%p> [ %s + 0x%lx ]",
-                                             (void*)address, name, offset);
+                                             (void *)address, name, offset);
                        }
 
                        vml = vml->next;
@@ -128,19 +128,9 @@ static int printk_address(unsigned long address)
        write_unlock_irq(&tasklist_lock);
 
        /* we were unable to find this address anywhere */
-       return printk("[<0x%p>]", (void*)address);
+       return printk("[<0x%p>]", (void *)address);
 }
 
-#define trace_buffer_save(x) \
-       do { \
-               (x) = bfin_read_TBUFCTL(); \
-               bfin_write_TBUFCTL((x) & ~TBUFEN); \
-       } while (0)
-#define trace_buffer_restore(x) \
-       do { \
-               bfin_write_TBUFCTL((x));        \
-       } while (0)
-
 asmlinkage void trap_c(struct pt_regs *fp)
 {
        int j, sig = 0;
@@ -203,15 +193,14 @@ asmlinkage void trap_c(struct pt_regs *fp)
 #else
        /* 0x02 - User Defined, Caught by default */
 #endif
-       /* 0x03  - Atomic test and set */
+       /* 0x03 - User Defined, userspace stack overflow */
        case VEC_EXCPT03:
                info.si_code = SEGV_STACKFLOW;
                sig = SIGSEGV;
                printk(KERN_EMERG EXC_0x03);
                CHK_DEBUGGER_TRAP();
                break;
-       /* 0x04 - spinlock - handled by _ex_spinlock,
-               getting here is an error */
+       /* 0x04 - User Defined, Caught by default */
        /* 0x05 - User Defined, Caught by default */
        /* 0x06 - User Defined, Caught by default */
        /* 0x07 - User Defined, Caught by default */
@@ -547,29 +536,28 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr)
                printk(KERN_EMERG "TEXT = 0x%p-0x%p  DATA = 0x%p-0x%p\n"
                       KERN_EMERG "BSS = 0x%p-0x%p   USER-STACK = 0x%p\n"
                       KERN_EMERG "\n",
-                      (void*)current->mm->start_code,
-                      (void*)current->mm->end_code,
-                      (void*)current->mm->start_data,
-                      (void*)current->mm->end_data,
-                      (void*)current->mm->end_data,
-                      (void*)current->mm->brk,
-                      (void*)current->mm->start_stack);
+                      (void *)current->mm->start_code,
+                      (void *)current->mm->end_code,
+                      (void *)current->mm->start_data,
+                      (void *)current->mm->end_data,
+                      (void *)current->mm->end_data,
+                      (void *)current->mm->brk,
+                      (void *)current->mm->start_stack);
        }
 
        printk(KERN_EMERG "return address: [0x%p]; contents of:", retaddr);
-       if (retaddr != 0 && retaddr <= (void*)physical_mem_end
+       if (retaddr != 0 && retaddr <= (void *)physical_mem_end
 #if L1_CODE_LENGTH != 0
            /* FIXME: Copy the code out of L1 Instruction SRAM through dma
               memcpy.  */
-           && !(retaddr >= (void*)L1_CODE_START
-                && retaddr < (void*)(L1_CODE_START + L1_CODE_LENGTH))
+           && !(retaddr >= (void *)L1_CODE_START
+                && retaddr < (void *)(L1_CODE_START + L1_CODE_LENGTH))
 #endif
        ) {
                int i = ((unsigned int)retaddr & 0xFFFFFFF0) - 32;
                unsigned short x = 0;
-               for (; i < ((unsigned int)retaddr & 0xFFFFFFF0 ) + 32 ;
-                       i += 2) {
-                       if ( !(i & 0xF) )
+               for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) {
+                       if (!(i & 0xF))
                                printk(KERN_EMERG "\n" KERN_EMERG
                                        "0x%08x: ", i);
 
@@ -588,7 +576,7 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr)
                                        " The rest of this error"
                                        " is meanless\n");
 #endif
-                       if ( i == (unsigned int)retaddr )
+                       if (i == (unsigned int)retaddr)
                                printk("[%04x]", x);
                        else
                                printk(" %04x ", x);
@@ -681,8 +669,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
                break;
        }
 
-       printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void*)bfin_read_DCPLB_FAULT_ADDR());
-       printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void*)bfin_read_ICPLB_FAULT_ADDR());
+       printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR());
+       printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR());
        dump_bfin_regs(fp, (void *)fp->retx);
        dump_stack();
        panic("Unrecoverable event\n");
index 1ef1e36b3957d95690efddea5416d52c58755975..d06f860f47900a5b6e09edf4b6629b6c9908c9e7 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/mem_map.h>
+#include <asm/page.h>
 
 OUTPUT_FORMAT("elf32-bfin")
 ENTRY(__start)
@@ -63,8 +64,8 @@ SECTIONS
 
        .data :
        {
+               . = ALIGN(PAGE_SIZE);
                __sdata = .;
-               . = ALIGN(0x2000);
                *(.data.init_task)
                DATA_DATA
                CONSTRUCTORS
@@ -72,14 +73,14 @@ SECTIONS
                . = ALIGN(32);
                *(.data.cacheline_aligned)
 
-               . = ALIGN(0x2000);
+               . = ALIGN(PAGE_SIZE);
                __edata = .;
        }
 
+       . = ALIGN(PAGE_SIZE);
        ___init_begin = .;
        .init :
        {
-               . = ALIGN(4096);
                __sinittext = .;
                *(.init.text)
                __einittext = .;
@@ -152,9 +153,10 @@ SECTIONS
                __ebss_b_l1 = .;
        }
 
-       ___init_end = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1);
+       . = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1);
+       ___init_end = ALIGN(PAGE_SIZE);
 
-       .bss LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1) :
+       .bss ___init_end :
        {
                . = ALIGN(4);
                ___bss_start = .;
index 2ad47c4254ba579ea423a0011cb1a26736fadc8d..4eeefd86907f0ff460f04768b6eaf2c90b97bb52 100644 (file)
@@ -6,6 +6,5 @@
 
 int strcmp(const char *dest, const char *src)
 {
-               return __inline_strcmp(dest, src);
+       return __inline_strcmp(dest, src);
 }
-
index 4dc835a8a19b080bc9e91d935e8630c8f8849e37..534589db725619797bb44c51fe296ea8fbea9bde 100644 (file)
@@ -6,6 +6,5 @@
 
 char *strcpy(char *dest, const char *src)
 {
-               return __inline_strcpy(dest, src);
+       return __inline_strcpy(dest, src);
 }
-
index 947bcfe3f3bba630e3b0d4f294c4b31d0355a6c2..d791f120bff7388252f3add58d20aade76cc03b2 100644 (file)
@@ -6,6 +6,5 @@
 
 int strncmp(const char *cs, const char *ct, size_t count)
 {
-               return __inline_strncmp(cs, ct, count);
+       return __inline_strncmp(cs, ct, count);
 }
-
index 77a9b2e950977bcb7d5fe213015dceef1308eb05..1fecb5c71ffb21ec581d157b81ef2d2d8776bc8c 100644 (file)
@@ -6,6 +6,5 @@
 
 char *strncpy(char *dest, const char *src, size_t n)
 {
-               return __inline_strncpy(dest, src, n);
+       return __inline_strncpy(dest, src, n);
 }
-
index 76d2c2b8579a7dbedea91ec7fc360bf264d73daf..8cce1736360d3b8904df3acc9be3fa8a709588e2 100644 (file)
@@ -4,6 +4,6 @@
 
 extra-y := head.o
 
-obj-y := ints-priority.o
+obj-y := ints-priority.o dma.o
 
-obj-$(CONFIG_CPU_FREQ_BF533) += cpu.o
+obj-$(CONFIG_CPU_FREQ)   += cpu.o
index edd31ce4f8d2d62fccad4aede373b70c4fafc6fa..4545f363e641d9f1aafd3d9dbcaa19a3a00ba53f 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 
 /*
@@ -51,11 +51,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
                .size = 0x00020000,
                .offset = 0,
                .mask_flags = MTD_CAP_ROM
-       },{
+       }, {
                .name = "kernel",
                .size = 0xe0000,
                .offset = 0x20000
-       },{
+       }, {
                .name = "file system",
                .size = 0x700000,
                .offset = 0x00100000,
@@ -98,7 +98,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
                .platform_data = &bfin_spi_flash_data,
                .controller_data = &spi_flash_chip_info,
                .mode = SPI_MODE_3,
-       },{
+       }, {
                .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
                .max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
                .bus_num = 1,               /* Framework bus number */
@@ -145,7 +145,7 @@ static struct resource smc91x_resources[] = {
                .start = 0x20200300,
                .end = 0x20200300 + 16,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PF0,
                .end = IRQ_PF0,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -194,11 +194,11 @@ static struct resource isp1362_hcd_resources[] = {
                .start = 0x20308000,
                .end = 0x20308000,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = 0x20308004,
                .end = 0x20308004,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PF4,
                .end = IRQ_PF4,
                .flags = IORESOURCE_IRQ,
index 0b522d95160d4d189d19e2146ac1f3933b9b0649..0000b8f1239c5030a6b3e56cfd1b7ab907a18632 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 
 /*
@@ -61,7 +61,7 @@ static struct resource smc91x_resources[] = {
                .start = 0x20310300,
                .end = 0x20310300 + 16,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PF9,
                .end = IRQ_PF9,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -85,11 +85,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
                .size = 0x00020000,
                .offset = 0,
                .mask_flags = MTD_CAP_ROM
-       },{
+       }, {
                .name = "kernel",
                .size = 0xe0000,
                .offset = 0x20000
-       },{
+       }, {
                .name = "file system",
                .size = 0x700000,
                .offset = 0x00100000,
index c0f43ccfbfb5320b2281125b1f1e4d8f9c0f2aca..9bc1f0d0ab508692f12791840ea9d30efd68a77c 100644 (file)
@@ -30,7 +30,7 @@
 
 #include <linux/device.h>
 #include <linux/platform_device.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -53,11 +53,11 @@ static struct resource smc91x_resources[] = {
                .start = 0x20300300,
                .end = 0x20300300 + 16,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PROG_INTB,
                .end = IRQ_PROG_INTB,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-       },{
+       }, {
                /*
                 *  denotes the flag pin and is used directly if
                 *  CONFIG_IRQCHIP_DEMUX_GPIO is defined.
index 9a472fe15833ea25883fc0ac236275a7431a9f58..a9143c4cbdcd110d3f88ddb697e04cab015e6e19 100644 (file)
@@ -37,7 +37,7 @@
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb_isp1362.h>
 #endif
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 
 /*
@@ -62,7 +62,7 @@ static struct resource smc91x_resources[] = {
                .start = 0x20300300,
                .end = 0x20300300 + 16,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PF7,
                .end = IRQ_PF7,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -83,7 +83,7 @@ static struct resource net2272_bfin_resources[] = {
                .start = 0x20300000,
                .end = 0x20300000 + 0x100,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PF10,
                .end = IRQ_PF10,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -108,11 +108,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
                .size = 0x00020000,
                .offset = 0,
                .mask_flags = MTD_CAP_ROM
-       },{
+       }, {
                .name = "kernel",
                .size = 0xe0000,
                .offset = 0x20000
-       },{
+       }, {
                .name = "file system",
                .size = 0x700000,
                .offset = 0x00100000,
@@ -229,19 +229,19 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 
 #if defined(CONFIG_PBX)
        {
-               .modalias       = "fxs-spi",
-               .max_speed_hz   = 12500000,     /* max spi clock (SCK) speed in HZ */
-               .bus_num        = 1,
-               .chip_select    = 3,
-               .controller_data= &spi_si3xxx_chip_info,
+               .modalias = "fxs-spi",
+               .max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 3,
+               .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        = 1,
-               .chip_select    = 2,
-               .controller_data= &spi_si3xxx_chip_info,
+               .modalias = "fxo-spi",
+               .max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 2,
+               .controller_data = &spi_si3xxx_chip_info,
                .mode = SPI_MODE_3,
        },
 #endif
index 99547c4c290ebf73f73a6a7fa0a65996556550a3..6fd9cfd0a31bd1a330f89a1c803ca749abffa67b 100644 (file)
@@ -79,8 +79,7 @@ static int bf533_target(struct cpufreq_policy *policy,
        int i;
 
        struct cpufreq_freqs freqs;
-       if (cpufreq_frequency_table_target
-           (policy, bf533_freq_table, target_freq, relation, &index))
+       if (cpufreq_frequency_table_target(policy, bf533_freq_table, target_freq, relation, &index))
                return -EINVAL;
        cclk_mhz = bf533_freq_table[index].frequency;
        vco_mhz = bf533_freq_table[index].index;
diff --git a/arch/blackfin/mach-bf533/dma.c b/arch/blackfin/mach-bf533/dma.c
new file mode 100644 (file)
index 0000000..6c909cf
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * File:         arch/blackfin/mach-bf533/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * 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 <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+       (struct dma_register *) DMA0_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_NEXT_DESC_PTR,
+       (struct dma_register *) DMA3_NEXT_DESC_PTR,
+       (struct dma_register *) DMA4_NEXT_DESC_PTR,
+       (struct dma_register *) DMA5_NEXT_DESC_PTR,
+       (struct dma_register *) DMA6_NEXT_DESC_PTR,
+       (struct dma_register *) DMA7_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+       int ret_irq = -1;
+
+       switch (channel) {
+       case CH_PPI:
+               ret_irq = IRQ_PPI;
+               break;
+
+       case CH_SPORT0_RX:
+               ret_irq = IRQ_SPORT0_RX;
+               break;
+
+       case CH_SPORT0_TX:
+               ret_irq = IRQ_SPORT0_TX;
+               break;
+
+       case CH_SPORT1_RX:
+               ret_irq = IRQ_SPORT1_RX;
+               break;
+
+       case CH_SPORT1_TX:
+               ret_irq = IRQ_SPORT1_TX;
+               break;
+
+       case CH_SPI:
+               ret_irq = IRQ_SPI;
+               break;
+
+       case CH_UART_RX:
+               ret_irq = IRQ_UART_RX;
+               break;
+
+       case CH_UART_TX:
+               ret_irq = IRQ_UART_TX;
+               break;
+
+       case CH_MEM_STREAM0_SRC:
+       case CH_MEM_STREAM0_DEST:
+               ret_irq = IRQ_MEM_DMA0;
+               break;
+
+       case CH_MEM_STREAM1_SRC:
+       case CH_MEM_STREAM1_DEST:
+               ret_irq = IRQ_MEM_DMA1;
+               break;
+       }
+       return ret_irq;
+}
index 7e2aa8d0f44f624c35df56197fb2943812bdb113..7dd0e9c3a936402e4e9470677114b8155eababbe 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/blackfin.h>
+#include <asm/trace.h>
 #if CONFIG_BFIN_KERNEL_CLOCK
 #include <asm/mach/mem_init.h>
 #endif
@@ -96,6 +97,10 @@ ENTRY(__start)
        M2 = r0;
        M3 = r0;
 
+       trace_buffer_start(p0,r0);
+       P0 = R1;
+       R0 = R1;
+
 #if CONFIG_DEBUG_KERNEL_START
 
 /*
index a3e1789167beec2c60ad1d17f19b6a2c393480a1..7d79e0f9503deb989f33a1df82e3906c02b76a21 100644 (file)
@@ -28,8 +28,8 @@
  */
 
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
 
 void program_IAR(void)
 {
index f32d44215bb7fbd6bf74f0e9d20affc1db3c7de6..7e7c9c8ac5b263ac02f3aaa58ff349ed3060ee55 100644 (file)
@@ -4,6 +4,6 @@
 
 extra-y := head.o
 
-obj-y := ints-priority.o
+obj-y := ints-priority.o dma.o
 
 obj-$(CONFIG_CPU_FREQ)   += cpu.o
index 6a60618a78ecf9efa71d5ed35f66a55e24ea04ba..a8f947b727542fc2705107c515fe76556179fdaa 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 
 /*
@@ -53,11 +53,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
                .size = 0x00020000,
                .offset = 0,
                .mask_flags = MTD_CAP_ROM
-       },{
+       }, {
                .name = "kernel",
                .size = 0xe0000,
                .offset = 0x20000
-       },{
+       }, {
                .name = "file system",
                .size = 0x700000,
                .offset = 0x00100000,
@@ -202,7 +202,7 @@ static struct resource smc91x_resources[] = {
                .start = 0x20200300,
                .end = 0x20200300 + 16,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PF14,
                .end = IRQ_PF14,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -223,11 +223,11 @@ static struct resource isp1362_hcd_resources[] = {
                .start = 0x20308000,
                .end = 0x20308000,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = 0x20308004,
                .end = 0x20308004,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PG15,
                .end = IRQ_PG15,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -262,7 +262,7 @@ static struct resource net2272_bfin_resources[] = {
                .start = 0x20200000,
                .end = 0x20200000 + 0x100,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PF7,
                .end = IRQ_PF7,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -283,7 +283,7 @@ static struct resource bfin_uart_resources[] = {
                .start = 0xFFC00400,
                .end = 0xFFC004FF,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = 0xFFC02000,
                .end = 0xFFC020FF,
                .flags = IORESOURCE_MEM,
index e129a08d63de61330ad5677ba28cb71e81a788a3..a725cc8a92903100d371aacd928ec5623dec4970 100644 (file)
@@ -20,8 +20,7 @@
 #include <linux/module.h>
 #include <asm/blackfin.h>
 
-#if    defined(CONFIG_GENERIC_BOARD) \
-       || defined(CONFIG_BFIN537_STAMP)
+#if    defined(CONFIG_GENERIC_BOARD) || defined(CONFIG_BFIN537_STAMP)
 
 /*
  * Currently the MAC address is saved in Flash by U-Boot
@@ -43,7 +42,7 @@ void get_bf537_ether_addr(char *addr)
  */
 void get_bf537_ether_addr(char *addr)
 {
-       printk(KERN_WARNING "%s: No valid Ethernet MAC address found\n",__FILE__);
+       printk(KERN_WARNING "%s: No valid Ethernet MAC address found\n", __FILE__);
 }
 
 #endif
index fd57e7439e0fa7347429e12906fc5a96c6cf6ba0..648d984e98d6ce45b536a9a92b06a8c8e4333e5e 100644 (file)
@@ -35,9 +35,9 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb_isp1362.h>
-#include <asm/irq.h>
-#include <asm/bfin5xx_spi.h>
+#include <linux/irq.h>
 #include <linux/usb_sl811.h>
+#include <asm/bfin5xx_spi.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -54,19 +54,19 @@ 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_PROG_INTA,
                .end = IRQ_PROG_INTA,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-       },{
+       }, {
                .start = IRQ_PF4,
                .end = IRQ_PF4,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-       },{
+       }, {
                .start = 6, /* Card Detect PF6 */
                .end = 6,
                .flags = IORESOURCE_IRQ,
@@ -95,11 +95,11 @@ static struct resource smc91x_resources[] = {
                .start = 0x20300300,
                .end = 0x20300300 + 16,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PROG_INTB,
                .end = IRQ_PROG_INTB,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-       },{
+       }, {
                /*
                 *  denotes the flag pin and is used directly if
                 *  CONFIG_IRQCHIP_DEMUX_GPIO is defined.
@@ -123,15 +123,15 @@ static struct resource sl811_hcd_resources[] = {
                .start = 0x20340000,
                .end = 0x20340000,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = 0x20340004,
                .end = 0x20340004,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PROG_INTA,
                .end = IRQ_PROG_INTA,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-       },{
+       }, {
                .start = IRQ_PF0 + CONFIG_USB_SL811_BFIN_GPIO,
                .end = IRQ_PF0 + CONFIG_USB_SL811_BFIN_GPIO,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -179,15 +179,15 @@ static struct resource isp1362_hcd_resources[] = {
                .start = 0x20360000,
                .end = 0x20360000,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = 0x20360004,
                .end = 0x20360004,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PROG_INTA,
                .end = IRQ_PROG_INTA,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-       },{
+       }, {
                .start = IRQ_PF0 + CONFIG_USB_ISP1362_BFIN_GPIO,
                .end = IRQ_PF0 + CONFIG_USB_ISP1362_BFIN_GPIO,
                .flags = IORESOURCE_IRQ,
@@ -228,7 +228,7 @@ 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,
@@ -253,11 +253,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
                .size = 0x00020000,
                .offset = 0,
                .mask_flags = MTD_CAP_ROM
-       },{
+       }, {
                .name = "kernel",
                .size = 0xe0000,
                .offset = 0x20000
-       },{
+       }, {
                .name = "file system",
                .size = 0x700000,
                .offset = 0x00100000,
@@ -375,7 +375,7 @@ static struct resource bfin_uart_resources[] = {
                .start = 0xFFC00400,
                .end = 0xFFC004FF,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = 0xFFC02000,
                .end = 0xFFC020FF,
                .flags = IORESOURCE_MEM,
index 8aaf76dfce80831b0f5d71aa5d8ad1b8c672be9c..8806f1230f2da480c4a3b8e055466985fa0e4698 100644 (file)
@@ -37,7 +37,7 @@
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb_isp1362.h>
 #endif
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 #include <linux/usb_sl811.h>
 
@@ -58,15 +58,15 @@ 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,
@@ -95,7 +95,7 @@ static struct resource smc91x_resources[] = {
                .start = 0x20300300,
                .end = 0x20300300 + 16,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
 
                .start = IRQ_PF7,
                .end = IRQ_PF7,
@@ -116,11 +116,11 @@ 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,
@@ -167,11 +167,11 @@ 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,
@@ -212,7 +212,7 @@ 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,
@@ -238,11 +238,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
                .size = 0x00020000,
                .offset = 0,
                .mask_flags = MTD_CAP_ROM
-       },{
+       }, {
                .name = "kernel",
                .size = 0xe0000,
                .offset = 0x20000
-       },{
+       }, {
                .name = "file system",
                .size = 0x700000,
                .offset = 0x00100000,
@@ -294,16 +294,6 @@ static struct bfin5xx_spi_chip spi_mmc_chip_info = {
 };
 #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 = {
        .cs_change_per_word = 1,
@@ -392,24 +382,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
                .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        = 1,
-               .chip_select    = 3,
-               .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        = 1,
-               .chip_select    = 2,
-               .controller_data= &spi_si3xxx_chip_info,
-               .mode = SPI_MODE_3,
-       },
-#endif
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 {
        .modalias               = "ad7877",
@@ -451,7 +423,7 @@ static struct resource bfin_uart_resources[] = {
                .start = 0xFFC00400,
                .end = 0xFFC004FF,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = 0xFFC02000,
                .end = 0xFFC020FF,
                .flags = IORESOURCE_MEM,
index 3a29b4d15f252b79b329ee92bcceeaa2bd3abaae..9c43d775651088f219f948c80f0f9f9432014232 100644 (file)
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb_isp1362.h>
 #endif
-#include <asm/irq.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <asm/bfin5xx_spi.h>
 #include <linux/usb_sl811.h>
-
+#include <asm/bfin5xx_spi.h>
 #include <linux/spi/ad7877.h>
 
 /*
@@ -85,7 +83,7 @@ static struct platform_device *bfin_isp1761_devices[] = {
 
 int __init bfin_isp1761_init(void)
 {
-       unsigned int num_devices=ARRAY_SIZE(bfin_isp1761_devices);
+       unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
 
        printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
        set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
@@ -107,15 +105,15 @@ 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,
@@ -144,7 +142,7 @@ static struct resource smc91x_resources[] = {
                .start = 0x20300300,
                .end = 0x20300300 + 16,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
 
                .start = IRQ_PF7,
                .end = IRQ_PF7,
@@ -159,17 +157,39 @@ static struct platform_device smc91x_device = {
 };
 #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,
@@ -216,11 +236,11 @@ 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,
@@ -261,7 +281,7 @@ 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,
@@ -287,11 +307,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
                .size = 0x00020000,
                .offset = 0,
                .mask_flags = MTD_CAP_ROM
-       },{
+       }, {
                .name = "kernel",
                .size = 0xe0000,
                .offset = 0x20000
-       },{
+       }, {
                .name = "file system",
                .size = 0x700000,
                .offset = 0x00100000,
@@ -361,7 +381,6 @@ static struct bfin5xx_spi_chip ad5304_chip_info = {
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-//     .cs_change_per_word = 1,
        .enable_dma = 0,
        .bits_per_word = 16,
 };
@@ -449,19 +468,19 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #endif
 #if defined(CONFIG_PBX)
        {
-               .modalias       = "fxs-spi",
-               .max_speed_hz   = 12500000,     /* max spi clock (SCK) speed in HZ */
-               .bus_num        = 1,
-               .chip_select    = 3,
-               .controller_data= &spi_si3xxx_chip_info,
+               .modalias = "fxs-spi",
+               .max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 3,
+               .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        = 1,
-               .chip_select    = 2,
-               .controller_data= &spi_si3xxx_chip_info,
+               .modalias = "fxo-spi",
+               .max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 2,
+               .controller_data = &spi_si3xxx_chip_info,
                .mode = SPI_MODE_3,
        },
 #endif
@@ -516,7 +535,7 @@ static struct resource bfin_uart_resources[] = {
                .start = 0xFFC00400,
                .end = 0xFFC004FF,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = 0xFFC02000,
                .end = 0xFFC020FF,
                .flags = IORESOURCE_MEM,
@@ -571,6 +590,10 @@ static struct platform_device *stamp_devices[] __initdata = {
        &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
diff --git a/arch/blackfin/mach-bf537/dma.c b/arch/blackfin/mach-bf537/dma.c
new file mode 100644 (file)
index 0000000..706cb97
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * File:         arch/blackfin/mach-bf537/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ *               Copyright 2004-2007 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 <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+       (struct dma_register *) DMA0_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_NEXT_DESC_PTR,
+       (struct dma_register *) DMA3_NEXT_DESC_PTR,
+       (struct dma_register *) DMA4_NEXT_DESC_PTR,
+       (struct dma_register *) DMA5_NEXT_DESC_PTR,
+       (struct dma_register *) DMA6_NEXT_DESC_PTR,
+       (struct dma_register *) DMA7_NEXT_DESC_PTR,
+       (struct dma_register *) DMA8_NEXT_DESC_PTR,
+       (struct dma_register *) DMA9_NEXT_DESC_PTR,
+       (struct dma_register *) DMA10_NEXT_DESC_PTR,
+       (struct dma_register *) DMA11_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+       int ret_irq = -1;
+
+       switch (channel) {
+       case CH_PPI:
+               ret_irq = IRQ_PPI;
+               break;
+
+       case CH_EMAC_RX:
+               ret_irq = IRQ_MAC_RX;
+               break;
+
+       case CH_EMAC_TX:
+               ret_irq = IRQ_MAC_TX;
+               break;
+
+       case CH_UART1_RX:
+               ret_irq = IRQ_UART1_RX;
+               break;
+
+       case CH_UART1_TX:
+               ret_irq = IRQ_UART1_TX;
+               break;
+
+       case CH_SPORT0_RX:
+               ret_irq = IRQ_SPORT0_RX;
+               break;
+
+       case CH_SPORT0_TX:
+               ret_irq = IRQ_SPORT0_TX;
+               break;
+
+       case CH_SPORT1_RX:
+               ret_irq = IRQ_SPORT1_RX;
+               break;
+
+       case CH_SPORT1_TX:
+               ret_irq = IRQ_SPORT1_TX;
+               break;
+
+       case CH_SPI:
+               ret_irq = IRQ_SPI;
+               break;
+
+       case CH_UART_RX:
+               ret_irq = IRQ_UART_RX;
+               break;
+
+       case CH_UART_TX:
+               ret_irq = IRQ_UART_TX;
+               break;
+
+       case CH_MEM_STREAM0_SRC:
+       case CH_MEM_STREAM0_DEST:
+               ret_irq = IRQ_MEM_DMA0;
+               break;
+
+       case CH_MEM_STREAM1_SRC:
+       case CH_MEM_STREAM1_DEST:
+               ret_irq = IRQ_MEM_DMA1;
+               break;
+       }
+       return ret_irq;
+}
index 7d902bbd860fa652ce26722a899d5d277b86ac0c..429c8a1019dab0de10bc9e7dfdc2f1392994cc42 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/blackfin.h>
+#include <asm/trace.h>
+
 #if CONFIG_BFIN_KERNEL_CLOCK
 #include <asm/mach/mem_init.h>
 #endif
@@ -93,6 +95,10 @@ ENTRY(__start)
        M2 = r0;
        M3 = r0;
 
+       trace_buffer_start(p0,r0);
+       P0 = R1;
+       R0 = R1;
+
        /* Turn off the icache */
        p0.l = (IMEM_CONTROL & 0xFFFF);
        p0.h = (IMEM_CONTROL >> 16);
index 2dbf3df465d193ba085f09504ac0b96aee9732a5..a8b915f202ec8870162b2822bc79057e1e38a8b1 100644 (file)
@@ -28,8 +28,8 @@
  */
 
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
 
 void program_IAR(void)
 {
diff --git a/arch/blackfin/mach-bf548/Kconfig b/arch/blackfin/mach-bf548/Kconfig
new file mode 100644 (file)
index 0000000..e78b03d
--- /dev/null
@@ -0,0 +1,316 @@
+if (BF54x)
+
+menu "BF548 Specific Configuration"
+
+comment "Interrupt Priority Assignment"
+menu "Priority"
+
+config IRQ_PLL_WAKEUP
+       int "IRQ_PLL_WAKEUP"
+       default 7
+config IRQ_DMAC0_ERR
+       int "IRQ_DMAC0_ERR"
+       default 7
+config IRQ_EPPI0_ERR
+       int "IRQ_EPPI0_ERR"
+       default 7
+config IRQ_SPORT0_ERR
+       int "IRQ_SPORT0_ERR"
+       default 7
+config IRQ_SPORT1_ERR
+       int "IRQ_SPORT1_ERR"
+       default 7
+config IRQ_SPI0_ERR
+       int "IRQ_SPI0_ERR"
+       default 7
+config IRQ_UART0_ERR
+       int "IRQ_UART0_ERR"
+       default 7
+config IRQ_RTC
+       int "IRQ_RTC"
+       default 8
+config IRQ_EPPI0
+       int "IRQ_EPPI0"
+       default 8
+config IRQ_SPORT0_RX
+       int "IRQ_SPORT0_RX"
+       default 9
+config IRQ_SPORT0_TX
+       int "IRQ_SPORT0_TX"
+       default 9
+config IRQ_SPORT1_RX
+       int "IRQ_SPORT1_RX"
+       default 9
+config IRQ_SPORT1_TX
+       int "IRQ_SPORT1_TX"
+       default 9
+config IRQ_SPI0
+       int "IRQ_SPI0"
+       default 10
+config IRQ_UART0_RX
+       int "IRQ_UART0_RX"
+       default 10
+config IRQ_UART0_TX
+       int "IRQ_UART0_TX"
+       default 10
+config IRQ_TIMER8
+       int "IRQ_TIMER8"
+       default 11
+config IRQ_TIMER9
+       int "IRQ_TIMER9"
+       default 11
+config IRQ_TIMER10
+       int "IRQ_TIMER10"
+       default 11
+config IRQ_PINT0
+       int "IRQ_PINT0"
+       default 12
+config IRQ_PINT1
+       int "IRQ_PINT0"
+       default 12
+config IRQ_MDMAS0
+       int "IRQ_MDMAS0"
+       default 13
+config IRQ_MDMAS1
+       int "IRQ_DMDMAS1"
+       default 13
+config IRQ_WATCHDOG
+       int "IRQ_WATCHDOG"
+       default 13
+config IRQ_DMAC1_ERR
+       int "IRQ_DMAC1_ERR"
+       default 7
+config IRQ_SPORT2_ERR
+       int "IRQ_SPORT2_ERR"
+       default 7
+config IRQ_SPORT3_ERR
+       int "IRQ_SPORT3_ERR"
+       default 7
+config IRQ_MXVR_DATA
+       int "IRQ MXVR Data"
+       default 7
+config IRQ_SPI1_ERR
+       int "IRQ_SPI1_ERR"
+       default 7
+config IRQ_SPI2_ERR
+       int "IRQ_SPI2_ERR"
+       default 7
+config IRQ_UART1_ERR
+       int "IRQ_UART1_ERR"
+       default 7
+config IRQ_UART2_ERR
+       int "IRQ_UART2_ERR"
+       default 7
+config IRQ_CAN0_ERR
+       int "IRQ_CAN0_ERR"
+       default 7
+config IRQ_SPORT2_RX
+       int "IRQ_SPORT2_RX"
+       default 9
+config IRQ_SPORT2_TX
+       int "IRQ_SPORT2_TX"
+       default 9
+config IRQ_SPORT3_RX
+       int "IRQ_SPORT3_RX"
+       default 9
+config IRQ_SPORT3_TX
+       int "IRQ_SPORT3_TX"
+       default 9
+config IRQ_EPPI1
+       int "IRQ_EPPI1"
+       default 9
+config IRQ_EPPI2
+       int "IRQ_EPPI2"
+       default 9
+config IRQ_SPI1
+       int "IRQ_SPI1"
+       default 10
+config IRQ_SPI2
+       int "IRQ_SPI2"
+       default 10
+config IRQ_UART1_RX
+       int "IRQ_UART1_RX"
+       default 10
+config IRQ_UART1_TX
+       int "IRQ_UART1_TX"
+       default 10
+config IRQ_ATAPI_RX
+       int "IRQ_ATAPI_RX"
+       default 10
+config IRQ_ATAPI_TX
+       int "IRQ_ATAPI_TX"
+       default 10
+config IRQ_TWI0
+       int "IRQ_TWI0"
+       default 11
+config IRQ_TWI1
+       int "IRQ_TWI1"
+       default 11
+config IRQ_CAN0_RX
+       int "IRQ_CAN_RX"
+       default 11
+config IRQ_CAN0_TX
+       int "IRQ_CAN_TX"
+       default 11
+config IRQ_MDMAS2
+       int "IRQ_MDMAS2"
+       default 13
+config IRQ_MDMAS3
+       int "IRQ_DMMAS3"
+       default 13
+config IRQ_MXVR_ERR
+       int "IRQ_MXVR_ERR"
+       default 11
+config IRQ_MXVR_MSG
+       int "IRQ_MXVR_MSG"
+       default 11
+config IRQ_MXVR_PKT
+       int "IRQ_MXVR_PKT"
+       default 11
+config IRQ_EPPI1_ERR
+       int "IRQ_EPPI1_ERR"
+       default 7
+config IRQ_EPPI2_ERR
+       int "IRQ_EPPI2_ERR"
+       default 7
+config IRQ_UART3_ERR
+       int "IRQ_UART3_ERR"
+       default 7
+config IRQ_HOST_ERR
+       int "IRQ_HOST_ERR"
+       default 7
+config IRQ_PIXC_ERR
+       int "IRQ_PIXC_ERR"
+       default 7
+config IRQ_NFC_ERR
+       int "IRQ_NFC_ERR"
+       default 7
+config IRQ_ATAPI_ERR
+       int "IRQ_ATAPI_ERR"
+       default 7
+config IRQ_CAN1_ERR
+       int "IRQ_CAN1_ERR"
+       default 7
+config IRQ_HS_DMA_ERR
+       int "IRQ Handshake DMA Status"
+       default 7
+config IRQ_PIXC_IN0
+       int "IRQ PIXC IN0"
+       default 8
+config IRQ_PIXC_IN1
+       int "IRQ PIXC IN1"
+       default 8
+config IRQ_PIXC_OUT
+       int "IRQ PIXC OUT"
+       default 8
+config IRQ_SDH
+       int "IRQ SDH"
+       default 8
+config IRQ_CNT
+       int "IRQ CNT"
+       default 8
+config IRQ_KEY
+       int "IRQ KEY"
+       default 8
+config IRQ_CAN1_RX
+       int "IRQ CAN1 RX"
+       default 11
+config IRQ_CAN1_TX
+       int "IRQ_CAN1_TX"
+       default 11
+config IRQ_SDH_MASK0
+       int "IRQ_SDH_MASK0"
+       default 11
+config IRQ_SDH_MASK1
+       int "IRQ_SDH_MASK1"
+       default 11
+config IRQ_USB_INT0
+       int "IRQ USB INT0"
+       default 11
+config IRQ_USB_INT1
+       int "IRQ USB INT1"
+       default 11
+config IRQ_USB_INT2
+       int "IRQ USB INT2"
+       default 11
+config IRQ_USB_DMA
+       int "IRQ USB DMA"
+       default 11
+config IRQ_OTPSEC
+       int "IRQ OPTSEC"
+       default 11
+config IRQ_TIMER0
+       int "IRQ_TIMER0"
+       default 11
+config IRQ_TIMER1
+       int "IRQ_TIMER1"
+       default 11
+config IRQ_TIMER2
+       int "IRQ_TIMER2"
+       default 11
+config IRQ_TIMER3
+       int "IRQ_TIMER3"
+       default 11
+config IRQ_TIMER4
+       int "IRQ_TIMER4"
+       default 11
+config IRQ_TIMER5
+       int "IRQ_TIMER5"
+       default 11
+config IRQ_TIMER6
+       int "IRQ_TIMER6"
+       default 11
+config IRQ_TIMER7
+       int "IRQ_TIMER7"
+       default 11
+config IRQ_PINT2
+       int "IRQ_PIN2"
+       default 11
+config IRQ_PINT3
+       int "IRQ_PIN3"
+       default 11
+
+       help
+         Enter the priority numbers between 7-13 ONLY.  Others are Reserved.
+         This applies to all the above.  It is not recommended to assign the
+         highest priority number 7 to UART or any other device.
+
+endmenu
+
+comment "Pin Interrupt to Port Assignment"
+menu "Assignment"
+
+config PINTx_REASSIGN
+       bool "Reprogram PINT Assignment"
+       default n
+       help
+         The interrupt assignment registers controls the pin-to-interrupt
+         assignment in a byte-wide manner. Each option allows you to select
+         a set of pins (High/Low Byte) of an specific Port being mapped
+         to one of the four PIN Interrupts IRQ_PINTx.
+
+         You shouldn't change any of these unless you know exactly what you're doing.
+         Please consult the Blackfin BF54x Processor Hardware Reference Manual.
+
+config PINT0_ASSIGN
+       hex "PINT0_ASSIGN"
+       depends on PINTx_REASSIGN
+       default 0x00000101
+config PINT1_ASSIGN
+       hex "PINT1_ASSIGN"
+       depends on PINTx_REASSIGN
+       default 0x01010000
+config PINT2_ASSIGN
+       hex "PINT2_ASSIGN"
+       depends on PINTx_REASSIGN
+       default 0x00000101
+config PINT3_ASSIGN
+       hex "PINT3_ASSIGN"
+       depends on PINTx_REASSIGN
+       default 0x02020303
+
+endmenu
+
+endmenu
+
+endif
diff --git a/arch/blackfin/mach-bf548/Makefile b/arch/blackfin/mach-bf548/Makefile
new file mode 100644 (file)
index 0000000..060ad78
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# arch/blackfin/mach-bf537/Makefile
+#
+
+extra-y := head.o
+
+obj-y := ints-priority.o dma.o gpio.o
+
+obj-$(CONFIG_CPU_FREQ)   += cpu.o
diff --git a/arch/blackfin/mach-bf548/boards/Makefile b/arch/blackfin/mach-bf548/boards/Makefile
new file mode 100644 (file)
index 0000000..486e07c
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# arch/blackfin/mach-bf548/boards/Makefile
+#
+
+obj-$(CONFIG_BFIN548_EZKIT)            += ezkit.o led.o
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
new file mode 100644 (file)
index 0000000..96ad95f
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * File:         arch/blackfin/mach-bf548/boards/ezkit.c
+ * Based on:     arch/blackfin/mach-bf537/boards/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2007 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/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/irq.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/bfin5xx_spi.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "ADSP-BF548-EZKIT";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+
+#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_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
+#ifdef CONFIG_SERIAL_BFIN_UART2
+       {
+               .start = 0xFFC02100,
+               .end = 0xFFC021FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART3
+       {
+               .start = 0xFFC03100,
+               .end = 0xFFC031FF,
+       },
+#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
+
+static struct platform_device *ezkit_devices[] __initdata = {
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+};
+
+static int __init stamp_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
+       return 0;
+}
+
+arch_initcall(stamp_init);
diff --git a/arch/blackfin/mach-bf548/boards/led.S b/arch/blackfin/mach-bf548/boards/led.S
new file mode 100644 (file)
index 0000000..f47daf3
--- /dev/null
@@ -0,0 +1,172 @@
+/****************************************************
+ * LED1 ---- PG6        LED2 ---- PG7               *
+ * LED3 ---- PG8        LED4 ---- PG9               *
+ * LED5 ---- PG10       LED6 ---- PG11              *
+ ****************************************************/
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+
+/* All functions in this file save the registers they uses.
+   So there is no need to save any registers before calling them.  */
+
+       .text;
+
+/* Initialize LEDs.  */
+
+ENTRY(_led_init)
+       LINK 0;
+       [--SP] = P0;
+       [--SP] = R0;
+       [--SP] = R1;
+       [--SP] = R2;
+       R1 = (PG6|PG7|PG8|PG9|PG10|PG11)(Z);
+       R2 = ~R1;
+
+       P0.H = hi(PORTG_FER);
+       P0.L = lo(PORTG_FER);
+       R0 = W[P0](Z);
+       SSYNC;
+       R0 = R0 & R2;
+       W[P0] = R0.L;
+       SSYNC;
+
+       P0.H = hi(PORTG_DIR_SET);
+       P0.L = lo(PORTG_DIR_SET);
+       W[P0] = R1.L;
+       SSYNC;
+
+       P0.H = hi(PORTG_INEN);
+       P0.L = lo(PORTG_INEN);
+       R0 = W[P0](Z);
+       SSYNC;
+       R0 = R0 & R2;
+       W[P0] = R0.L;
+       SSYNC;
+
+       R2 = [SP++];
+       R1 = [SP++];
+       R0 = [SP++];
+       P0 = [SP++];
+       RTS;
+       .size   _led_init, .-_led_init
+
+/* Set one LED on. Leave other LEDs unchanged.
+   It expects the LED number passed through R0.  */
+
+ENTRY(_led_on)
+       LINK 0;
+       [--SP] = P0;
+       [--SP] = R1;
+       CALL _led_init;
+       R1 = 1;
+       R0 += 5;
+       R1 <<= R0;
+       P0.H = hi(PORTG_SET);
+       P0.L = lo(PORTG_SET);
+       W[P0] = R1.L;
+       SSYNC;
+       R1 = [SP++];
+       P0 = [SP++];
+       UNLINK;
+       RTS;
+       .size   _led_on, .-_led_on
+
+/* Set one LED off. Leave other LEDs unchanged.  */
+
+ENTRY(_led_off)
+       LINK 0;
+       [--SP] = P0;
+       [--SP] = R1;
+       CALL _led_init;
+       R1 = 1;
+       R0 += 5;
+       R1 <<= R0;
+       P0.H = hi(PORTG_CLEAR);
+       P0.L = lo(PORTG_CLEAR);
+       W[P0] = R1.L;
+       SSYNC;
+       R1 = [SP++];
+       P0 = [SP++];
+       UNLINK;
+       RTS;
+       .size   _led_off, .-_led_off
+
+/* Toggle one LED. Leave other LEDs unchanged.  */
+
+ENTRY(_led_toggle)
+       LINK 0;
+       [--SP] = P0;
+       [--SP] = R1;
+       CALL _led_init;
+       R1 = 1;
+       R0 += 5;
+       R1 <<= R0;
+       P0.H = hi(PORTG);
+       P0.L = lo(PORTG);
+       R0 = W[P0](Z);
+       SSYNC;
+       R0 = R0 ^ R1;
+       W[P0] = R0.L;
+       SSYNC;
+       R1 = [SP++];
+       P0 = [SP++];
+       UNLINK;
+       RTS;
+       .size   _led_toggle, .-_led_toggle
+
+/* Display the number using LEDs in binary format.  */
+
+ENTRY(_led_disp_num)
+       LINK 0;
+       [--SP] = P0;
+       [--SP] = R1;
+       [--SP] = R2;
+       CALL _led_init;
+       R1 = 0x3f(X);
+       R0 = R0 & R1;
+       R2 = 6(X);
+       R0 <<= R2;
+       R1 <<= R2;
+       P0.H = hi(PORTG);
+       P0.L = lo(PORTG);
+       R2 = W[P0](Z);
+       SSYNC;
+       R1 = ~R1;
+       R2 = R2 & R1;
+       R2 = R2 | R0;
+       W[P0] = R2.L;
+       SSYNC;
+       R2 = [SP++];
+       R1 = [SP++];
+       P0 = [SP++];
+       UNLINK;
+       RTS;
+       .size   _led_disp_num, .-_led_disp_num
+
+/* Toggle the number using LEDs in binary format.  */
+
+ENTRY(_led_toggle_num)
+       LINK 0;
+       [--SP] = P0;
+       [--SP] = R1;
+       [--SP] = R2;
+       CALL _led_init;
+       R1 = 0x3f(X);
+       R0 = R0 & R1;
+       R1 = 6(X);
+       R0 <<= R1;
+       P0.H = hi(PORTG);
+       P0.L = lo(PORTG);
+       R1 = W[P0](Z);
+       SSYNC;
+       R1 = R1 ^ R0;
+       W[P0] = R1.L;
+       SSYNC;
+       R2 = [SP++];
+       R1 = [SP++];
+       P0 = [SP++];
+       UNLINK;
+       RTS;
+       .size   _led_toggle_num, .-_led_toggle_num
+
diff --git a/arch/blackfin/mach-bf548/cpu.c b/arch/blackfin/mach-bf548/cpu.c
new file mode 100644 (file)
index 0000000..4298a3c
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * File:         arch/blackfin/mach-bf548/cpu.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  clock scaling for the bf54x
+ *
+ * Modified:
+ *               Copyright 2004-2007 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/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <asm/dpmc.h>
+#include <linux/fs.h>
+#include <asm/bfin-global.h>
+
+/* CONFIG_CLKIN_HZ=25000000 */
+#define VCO5 (CONFIG_CLKIN_HZ*45)
+#define VCO4 (CONFIG_CLKIN_HZ*36)
+#define VCO3 (CONFIG_CLKIN_HZ*27)
+#define VCO2 (CONFIG_CLKIN_HZ*18)
+#define VCO1 (CONFIG_CLKIN_HZ*9)
+#define VCO(x) VCO##x
+
+#define MFREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+/* frequency */
+static struct cpufreq_frequency_table bf548_freq_table[] = {
+       MFREQ(1),
+       MFREQ(3),
+       {VCO4, VCO4 / 2}, {VCO4, VCO4},
+       MFREQ(5),
+       {0, CPUFREQ_TABLE_END},
+};
+
+/*
+ * dpmc_fops->ioctl()
+ * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ */
+static int bf548_getfreq(unsigned int cpu)
+{
+       unsigned long cclk_mhz;
+
+       /* The driver only support single cpu */
+       if (cpu == 0)
+               dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+       else
+               cclk_mhz = -1;
+
+       return cclk_mhz;
+}
+
+static int bf548_target(struct cpufreq_policy *policy,
+                           unsigned int target_freq, unsigned int relation)
+{
+       unsigned long cclk_mhz;
+       unsigned long vco_mhz;
+       unsigned long flags;
+       unsigned int index;
+       struct cpufreq_freqs freqs;
+
+       if (cpufreq_frequency_table_target(policy, bf548_freq_table, target_freq, relation, &index))
+               return -EINVAL;
+
+       cclk_mhz = bf548_freq_table[index].frequency;
+       vco_mhz = bf548_freq_table[index].index;
+
+       dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+       freqs.old = bf548_getfreq(0);
+       freqs.new = cclk_mhz;
+       freqs.cpu = 0;
+
+       pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+                cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+
+       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+       local_irq_save(flags);
+       dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+       local_irq_restore(flags);
+       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+       vco_mhz = get_vco();
+       cclk_mhz = get_cclk();
+       return 0;
+}
+
+/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+ * this platform, anyway.
+ */
+static int bf548_verify_speed(struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy, &bf548_freq_table);
+}
+
+static int __init __bf548_cpu_init(struct cpufreq_policy *policy)
+{
+       if (policy->cpu != 0)
+               return -EINVAL;
+
+       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+       /*Now ,only support one cpu */
+       policy->cur = bf548_getfreq(0);
+       cpufreq_frequency_table_get_attr(bf548_freq_table, policy->cpu);
+       return cpufreq_frequency_table_cpuinfo(policy, bf548_freq_table);
+}
+
+static struct freq_attr *bf548_freq_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
+static struct cpufreq_driver bf548_driver = {
+       .verify = bf548_verify_speed,
+       .target = bf548_target,
+       .get = bf548_getfreq,
+       .init = __bf548_cpu_init,
+       .name = "bf548",
+       .owner = THIS_MODULE,
+       .attr = bf548_freq_attr,
+};
+
+static int __init bf548_cpu_init(void)
+{
+       return cpufreq_register_driver(&bf548_driver);
+}
+
+static void __exit bf548_cpu_exit(void)
+{
+       cpufreq_unregister_driver(&bf548_driver);
+}
+
+MODULE_AUTHOR("Mickael Kang");
+MODULE_DESCRIPTION("cpufreq driver for BF548 CPU");
+MODULE_LICENSE("GPL");
+
+module_init(bf548_cpu_init);
+module_exit(bf548_cpu_exit);
diff --git a/arch/blackfin/mach-bf548/dma.c b/arch/blackfin/mach-bf548/dma.c
new file mode 100644 (file)
index 0000000..a818411
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * File:         arch/blackfin/mach-bf561/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ *               Copyright 2004-2007 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 <asm/blackfin.h>
+#include <asm/dma.h>
+
+ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+       (struct dma_register *) DMA0_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_NEXT_DESC_PTR,
+       (struct dma_register *) DMA3_NEXT_DESC_PTR,
+       (struct dma_register *) DMA4_NEXT_DESC_PTR,
+       (struct dma_register *) DMA5_NEXT_DESC_PTR,
+       (struct dma_register *) DMA6_NEXT_DESC_PTR,
+       (struct dma_register *) DMA7_NEXT_DESC_PTR,
+       (struct dma_register *) DMA8_NEXT_DESC_PTR,
+       (struct dma_register *) DMA9_NEXT_DESC_PTR,
+       (struct dma_register *) DMA10_NEXT_DESC_PTR,
+       (struct dma_register *) DMA11_NEXT_DESC_PTR,
+       (struct dma_register *) DMA12_NEXT_DESC_PTR,
+       (struct dma_register *) DMA13_NEXT_DESC_PTR,
+       (struct dma_register *) DMA14_NEXT_DESC_PTR,
+       (struct dma_register *) DMA15_NEXT_DESC_PTR,
+       (struct dma_register *) DMA16_NEXT_DESC_PTR,
+       (struct dma_register *) DMA17_NEXT_DESC_PTR,
+       (struct dma_register *) DMA18_NEXT_DESC_PTR,
+       (struct dma_register *) DMA19_NEXT_DESC_PTR,
+       (struct dma_register *) DMA20_NEXT_DESC_PTR,
+       (struct dma_register *) DMA21_NEXT_DESC_PTR,
+       (struct dma_register *) DMA22_NEXT_DESC_PTR,
+       (struct dma_register *) DMA23_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_D2_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_S2_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_D3_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_S3_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+       int ret_irq = -1;
+
+       switch (channel) {
+       case CH_SPORT0_RX:
+               ret_irq = IRQ_SPORT0_RX;
+               break;
+       case CH_SPORT0_TX:
+               ret_irq = IRQ_SPORT0_TX;
+               break;
+       case CH_SPORT1_RX:
+               ret_irq = IRQ_SPORT1_RX;
+               break;
+       case CH_SPORT1_TX:
+               ret_irq = IRQ_SPORT1_TX;
+       case CH_SPI0:
+               ret_irq = IRQ_SPI0;
+               break;
+       case CH_SPI1:
+               ret_irq = IRQ_SPI1;
+               break;
+       case CH_UART0_RX:
+               ret_irq = IRQ_UART_RX;
+               break;
+       case CH_UART0_TX:
+               ret_irq = IRQ_UART_TX;
+               break;
+       case CH_UART1_RX:
+               ret_irq = IRQ_UART_RX;
+               break;
+       case CH_UART1_TX:
+               ret_irq = IRQ_UART_TX;
+               break;
+       case CH_EPPI0:
+               ret_irq = IRQ_EPPI0;
+               break;
+       case CH_EPPI1:
+               ret_irq = IRQ_EPPI1;
+               break;
+       case CH_EPPI2:
+               ret_irq = IRQ_EPPI2;
+               break;
+       case CH_PIXC_IMAGE:
+               ret_irq = IRQ_PIXC_IN0;
+               break;
+       case CH_PIXC_OVERLAY:
+               ret_irq = IRQ_PIXC_IN1;
+               break;
+       case CH_PIXC_OUTPUT:
+               ret_irq = IRQ_PIXC_OUT;
+               break;
+       case CH_SPORT2_RX:
+               ret_irq = IRQ_SPORT2_RX;
+               break;
+       case CH_SPORT2_TX:
+               ret_irq = IRQ_SPORT2_TX;
+               break;
+       case CH_SPORT3_RX:
+               ret_irq = IRQ_SPORT3_RX;
+               break;
+       case CH_SPORT3_TX:
+               ret_irq = IRQ_SPORT3_TX;
+               break;
+       case CH_SDH:
+               ret_irq = IRQ_SDH;
+               break;
+       case CH_SPI2:
+               ret_irq = IRQ_SPI2;
+               break;
+       case CH_MEM_STREAM0_SRC:
+       case CH_MEM_STREAM0_DEST:
+               ret_irq = IRQ_MDMAS0;
+               break;
+       case CH_MEM_STREAM1_SRC:
+       case CH_MEM_STREAM1_DEST:
+               ret_irq = IRQ_MDMAS1;
+               break;
+       case CH_MEM_STREAM2_SRC:
+       case CH_MEM_STREAM2_DEST:
+               ret_irq = IRQ_MDMAS2;
+               break;
+       case CH_MEM_STREAM3_SRC:
+       case CH_MEM_STREAM3_DEST:
+               ret_irq = IRQ_MDMAS3;
+               break;
+       }
+       return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf548/gpio.c b/arch/blackfin/mach-bf548/gpio.c
new file mode 100644 (file)
index 0000000..0da5f00
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * File:         arch/blackfin/mach-bf548/gpio.c
+ * Based on:
+ * Author:       Michael Hennerich (hennerich@blackfin.uclinux.org)
+ *
+ * Created:
+ * Description:  GPIO Abstraction Layer
+ *
+ * Modified:
+ *               Copyright 2007 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/module.h>
+#include <linux/err.h>
+#include <asm/blackfin.h>
+#include <asm/gpio.h>
+#include <asm/portmux.h>
+#include <linux/irq.h>
+
+static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+       (struct gpio_port_t *)PORTA_FER,
+       (struct gpio_port_t *)PORTB_FER,
+       (struct gpio_port_t *)PORTC_FER,
+       (struct gpio_port_t *)PORTD_FER,
+       (struct gpio_port_t *)PORTE_FER,
+       (struct gpio_port_t *)PORTF_FER,
+       (struct gpio_port_t *)PORTG_FER,
+       (struct gpio_port_t *)PORTH_FER,
+       (struct gpio_port_t *)PORTI_FER,
+       (struct gpio_port_t *)PORTJ_FER,
+};
+
+static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+inline int check_gpio(unsigned short gpio)
+{
+       if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
+           || gpio == GPIO_PH14 || gpio == GPIO_PH15
+           || gpio == GPIO_PJ14 || gpio == GPIO_PJ15
+           || gpio > MAX_BLACKFIN_GPIOS)
+               return -EINVAL;
+       return 0;
+}
+
+inline void portmux_setup(unsigned short portno, unsigned short function)
+{
+       u32 pmux;
+
+       pmux = gpio_array[gpio_bank(portno)]->port_mux;
+
+       pmux &= ~(0x3 << (2 * gpio_sub_n(portno)));
+       pmux |= (function & 0x3) << (2 * gpio_sub_n(portno));
+
+       gpio_array[gpio_bank(portno)]->port_mux = pmux;
+
+}
+
+inline u16 get_portmux(unsigned short portno)
+{
+       u32 pmux;
+
+       pmux = gpio_array[gpio_bank(portno)]->port_mux;
+
+       return (pmux >> (2 * gpio_sub_n(portno)) & 0x3);
+
+}
+
+static void port_setup(unsigned short gpio, unsigned short usage)
+{
+       if (usage == GPIO_USAGE) {
+               if (gpio_array[gpio_bank(gpio)]->port_fer & gpio_bit(gpio))
+                       printk(KERN_WARNING
+                              "bfin-gpio: Possible Conflict with Peripheral "
+                              "usage and GPIO %d detected!\n", gpio);
+               gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
+       } else
+               gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
+       SSYNC();
+}
+
+static int __init bfin_gpio_init(void)
+{
+       printk(KERN_INFO "Blackfin GPIO Controller\n");
+
+       return 0;
+}
+
+arch_initcall(bfin_gpio_init);
+
+int peripheral_request(unsigned short per, const char *label)
+{
+       unsigned long flags;
+       unsigned short ident = P_IDENT(per);
+
+       if (!(per & P_DEFINED))
+               return -ENODEV;
+
+       if (check_gpio(ident) < 0)
+               return -EINVAL;
+
+       local_irq_save(flags);
+
+       if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
+               printk(KERN_ERR
+                      "%s: Peripheral %d is already reserved as GPIO!\n",
+                      __FUNCTION__, per);
+               dump_stack();
+               local_irq_restore(flags);
+               return -EBUSY;
+       }
+
+       if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
+
+               u16 funct = get_portmux(ident);
+
+               if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
+                       printk(KERN_ERR
+                              "%s: Peripheral %d is already reserved!\n",
+                              __FUNCTION__, per);
+                       dump_stack();
+                       local_irq_restore(flags);
+                       return -EBUSY;
+               }
+       }
+
+       reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
+
+       portmux_setup(ident, P_FUNCT2MUX(per));
+       port_setup(ident, PERIPHERAL_USAGE);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(peripheral_request);
+
+int peripheral_request_list(unsigned short per[], const char *label)
+{
+
+       u16 cnt;
+       int ret;
+
+       for (cnt = 0; per[cnt] != 0; cnt++) {
+               ret = peripheral_request(per[cnt], label);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(peripheral_request_list);
+
+void peripheral_free(unsigned short per)
+{
+       unsigned long flags;
+       unsigned short ident = P_IDENT(per);
+
+       if (!(per & P_DEFINED))
+               return;
+
+       if (check_gpio(ident) < 0)
+               return;
+
+       local_irq_save(flags);
+
+       if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
+               printk(KERN_ERR "bfin-gpio: Peripheral %d wasn't reserved!\n", per);
+               dump_stack();
+               local_irq_restore(flags);
+               return;
+       }
+
+       if (!(per & P_MAYSHARE)) {
+               port_setup(ident, GPIO_USAGE);
+       }
+
+       reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
+
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(peripheral_free);
+
+void peripheral_free_list(unsigned short per[])
+{
+       u16 cnt;
+
+       for (cnt = 0; per[cnt] != 0; cnt++) {
+               peripheral_free(per[cnt]);
+       }
+
+}
+EXPORT_SYMBOL(peripheral_free_list);
+
+/***********************************************************
+*
+* FUNCTIONS: Blackfin GPIO Driver
+*
+* INPUTS/OUTPUTS:
+* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
+*
+*
+* DESCRIPTION: Blackfin GPIO Driver API
+*
+* CAUTION:
+*************************************************************
+* MODIFICATION HISTORY :
+**************************************************************/
+
+int gpio_request(unsigned short gpio, const char *label)
+{
+       unsigned long flags;
+
+       if (check_gpio(gpio) < 0)
+               return -EINVAL;
+
+       local_irq_save(flags);
+
+       if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+               printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio);
+               dump_stack();
+               local_irq_restore(flags);
+               return -EBUSY;
+       }
+
+       if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+               printk(KERN_ERR
+                      "bfin-gpio: GPIO %d is already reserved as Peripheral!\n", gpio);
+               dump_stack();
+               local_irq_restore(flags);
+               return -EBUSY;
+       }
+
+       reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+
+       local_irq_restore(flags);
+
+       port_setup(gpio, GPIO_USAGE);
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned short gpio)
+{
+       unsigned long flags;
+
+       if (check_gpio(gpio) < 0)
+               return;
+
+       local_irq_save(flags);
+
+       if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
+               printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio);
+               dump_stack();
+               local_irq_restore(flags);
+               return;
+       }
+
+       reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_free);
+
+void gpio_direction_input(unsigned short gpio)
+{
+       unsigned long flags;
+
+       BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+
+       local_irq_save(flags);
+       gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
+       gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+void gpio_direction_output(unsigned short gpio)
+{
+       unsigned long flags;
+
+       BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+
+       local_irq_save(flags);
+       gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio);
+       gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+void gpio_set_value(unsigned short gpio, unsigned short arg)
+{
+       if (arg)
+               gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio);
+       else
+               gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio);
+
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+unsigned short gpio_get_value(unsigned short gpio)
+{
+       return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio)));
+}
+EXPORT_SYMBOL(gpio_get_value);
diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S
new file mode 100644 (file)
index 0000000..06751ae
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * File:         arch/blackfin/mach-bf548/head.S
+ * Based on:     arch/blackfin/mach-bf537/head.S
+ * Author:       Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
+ *
+ * Created:      1998
+ * Description:  Startup code for Blackfin BF548
+ *
+ * Modified:
+ *               Copyright 2004-2007 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/linkage.h>
+#include <asm/blackfin.h>
+#include <asm/trace.h>
+#if CONFIG_BFIN_KERNEL_CLOCK
+#include <asm/mach/mem_init.h>
+#endif
+
+.global __rambase
+.global __ramstart
+.global __ramend
+.extern ___bss_stop
+.extern ___bss_start
+.extern _bf53x_relocate_l1_mem
+
+#define INITIAL_STACK   0xFFB01000
+
+.text
+
+ENTRY(__start)
+ENTRY(__stext)
+       /* R0: argument of command line string, passed from uboot, save it */
+       R7 = R0;
+       /* Set the SYSCFG register */
+       R0 = 0x36;
+       SYSCFG = R0;   /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
+       R0 = 0;
+
+       /* Clear Out All the data and pointer  Registers*/
+       R1 = R0;
+       R2 = R0;
+       R3 = R0;
+       R4 = R0;
+       R5 = R0;
+       R6 = R0;
+
+       P0 = R0;
+       P1 = R0;
+       P2 = R0;
+       P3 = R0;
+       P4 = R0;
+       P5 = R0;
+
+       LC0 = r0;
+       LC1 = r0;
+       L0 = r0;
+       L1 = r0;
+       L2 = r0;
+       L3 = r0;
+
+       /* Clear Out All the DAG Registers*/
+       B0 = r0;
+       B1 = r0;
+       B2 = r0;
+       B3 = r0;
+
+       I0 = r0;
+       I1 = r0;
+       I2 = r0;
+       I3 = r0;
+
+       M0 = r0;
+       M1 = r0;
+       M2 = r0;
+       M3 = r0;
+
+       trace_buffer_start(p0,r0);
+       P0 = R1;
+       R0 = R1;
+
+       /* Turn off the icache */
+       p0.l = (IMEM_CONTROL & 0xFFFF);
+       p0.h = (IMEM_CONTROL >> 16);
+       R1 = [p0];
+       R0 = ~ENICPLB;
+       R0 = R0 & R1;
+       [p0] = R0;
+       SSYNC;
+
+       /* Turn off the dcache */
+       p0.l = (DMEM_CONTROL & 0xFFFF);
+       p0.h = (DMEM_CONTROL >> 16);
+       R1 = [p0];
+       R0 = ~ENDCPLB;
+       R0 = R0 & R1;
+       [p0] = R0;
+       SSYNC;
+
+       /* Initialize stack pointer */
+       SP.L = LO(INITIAL_STACK);
+       SP.H = HI(INITIAL_STACK);
+       FP = SP;
+       USP = SP;
+
+       /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
+       call _bf53x_relocate_l1_mem;
+#if CONFIG_BFIN_KERNEL_CLOCK
+       call _start_dma_code;
+#endif
+       /* Code for initializing Async memory banks */
+
+       p2.h = hi(EBIU_AMBCTL1);
+       p2.l = lo(EBIU_AMBCTL1);
+       r0.h = hi(AMBCTL1VAL);
+       r0.l = lo(AMBCTL1VAL);
+       [p2] = r0;
+       ssync;
+
+       p2.h = hi(EBIU_AMBCTL0);
+       p2.l = lo(EBIU_AMBCTL0);
+       r0.h = hi(AMBCTL0VAL);
+       r0.l = lo(AMBCTL0VAL);
+       [p2] = r0;
+       ssync;
+
+       p2.h = hi(EBIU_AMGCTL);
+       p2.l = lo(EBIU_AMGCTL);
+       r0 = AMGCTLVAL;
+       w[p2] = r0;
+       ssync;
+
+       /* This section keeps the processor in supervisor mode
+        * during kernel boot.  Switches to user mode at end of boot.
+        * See page 3-9 of Hardware Reference manual for documentation.
+        */
+
+       /* EVT15 = _real_start */
+
+       p0.l = lo(EVT15);
+       p0.h = hi(EVT15);
+       p1.l = _real_start;
+       p1.h = _real_start;
+       [p0] = p1;
+       csync;
+
+       p0.l = lo(IMASK);
+       p0.h = hi(IMASK);
+       p1.l = IMASK_IVG15;
+       p1.h = 0x0;
+       [p0] = p1;
+       csync;
+
+       raise 15;
+       p0.l = .LWAIT_HERE;
+       p0.h = .LWAIT_HERE;
+       reti = p0;
+#if defined (ANOMALY_05000281)
+       nop;
+       nop;
+       nop;
+#endif
+       rti;
+
+.LWAIT_HERE:
+       jump .LWAIT_HERE;
+
+ENTRY(_real_start)
+       [ -- sp ] = reti;
+       p0.l = lo(WDOG_CTL);
+       p0.h = hi(WDOG_CTL);
+       r0 = 0xAD6(z);
+       w[p0] = r0;     /* watchdog off for now */
+       ssync;
+
+       /* Code update for BSS size == 0
+        * Zero out the bss region.
+        */
+
+       p1.l = ___bss_start;
+       p1.h = ___bss_start;
+       p2.l = ___bss_stop;
+       p2.h = ___bss_stop;
+       r0 = 0;
+       p2 -= p1;
+       lsetup (.L_clear_bss, .L_clear_bss ) lc0 = p2;
+.L_clear_bss:
+       B[p1++] = r0;
+
+       /* In case there is a NULL pointer reference
+        * Zero out region before stext
+        */
+
+       p1.l = 0x0;
+       p1.h = 0x0;
+       r0.l = __stext;
+       r0.h = __stext;
+       r0 = r0 >> 1;
+       p2 = r0;
+       r0 = 0;
+       lsetup (.L_clear_zero, .L_clear_zero ) lc0 = p2;
+.L_clear_zero:
+       W[p1++] = r0;
+
+       /* pass the uboot arguments to the global value command line */
+       R0 = R7;
+       call _cmdline_init;
+
+       p1.l = __rambase;
+       p1.h = __rambase;
+       r0.l = __sdata;
+       r0.h = __sdata;
+       [p1] = r0;
+
+       p1.l = __ramstart;
+       p1.h = __ramstart;
+       p3.l = ___bss_stop;
+       p3.h = ___bss_stop;
+
+       r1 = p3;
+       [p1] = r1;
+
+
+       /*
+        *  load the current thread pointer and stack
+        */
+       r1.l = _init_thread_union;
+       r1.h = _init_thread_union;
+
+       r2.l = 0x2000;
+       r2.h = 0x0000;
+       r1 = r1 + r2;
+       sp = r1;
+       usp = sp;
+       fp = sp;
+       call _start_kernel;
+.L_exit:
+       jump.s  .L_exit;
+
+.section .l1.text
+#if CONFIG_BFIN_KERNEL_CLOCK
+ENTRY(_start_dma_code)
+
+       /* Enable PHY CLK buffer output */
+       p0.h = hi(VR_CTL);
+       p0.l = lo(VR_CTL);
+       r0.l = w[p0];
+       bitset(r0, 14);
+       w[p0] = r0.l;
+       ssync;
+
+       p0.h = hi(SIC_IWR);
+       p0.l = lo(SIC_IWR);
+       r0.l = 0x1;
+       r0.h = 0x0;
+       [p0] = r0;
+       SSYNC;
+
+       /*
+        *  Set PLL_CTL
+        *   - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
+        *   - [8]     = BYPASS    : BYPASS the PLL, run CLKIN into CCLK/SCLK
+        *   - [7]     = output delay (add 200ps of delay to mem signals)
+        *   - [6]     = input delay (add 200ps of input delay to mem signals)
+        *   - [5]     = PDWN      : 1=All Clocks off
+        *   - [3]     = STOPCK    : 1=Core Clock off
+        *   - [1]     = PLL_OFF   : 1=Disable Power to PLL
+        *   - [0]     = DF        : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
+        *   all other bits set to zero
+        */
+
+       p0.h = hi(PLL_LOCKCNT);
+       p0.l = lo(PLL_LOCKCNT);
+       r0 = 0x300(Z);
+       w[p0] = r0.l;
+       ssync;
+
+       P2.H = hi(EBIU_SDGCTL);
+       P2.L = lo(EBIU_SDGCTL);
+       R0 = [P2];
+       BITSET (R0, 24);
+       [P2] = R0;
+       SSYNC;
+
+       r0 = CONFIG_VCO_MULT & 63;       /* Load the VCO multiplier         */
+       r0 = r0 << 9;                    /* Shift it over,                  */
+       r1 = CLKIN_HALF;                 /* Do we need to divide CLKIN by 2?*/
+       r0 = r1 | r0;
+       r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
+       r1 = r1 << 8;                    /* Shift it over                   */
+       r0 = r1 | r0;                    /* add them all together           */
+
+       p0.h = hi(PLL_CTL);
+       p0.l = lo(PLL_CTL);              /* Load the address                */
+       cli r2;                          /* Disable interrupts              */
+       ssync;
+       w[p0] = r0.l;                    /* Set the value                   */
+       idle;                            /* Wait for the PLL to stablize    */
+       sti r2;                          /* Enable interrupts               */
+
+.Lcheck_again:
+       p0.h = hi(PLL_STAT);
+       p0.l = lo(PLL_STAT);
+       R0 = W[P0](Z);
+       CC = BITTST(R0,5);
+       if ! CC jump .Lcheck_again;
+
+       /* Configure SCLK & CCLK Dividers */
+       r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
+       p0.h = hi(PLL_DIV);
+       p0.l = lo(PLL_DIV);
+       w[p0] = r0.l;
+       ssync;
+
+       p0.l = lo(EBIU_SDRRC);
+       p0.h = hi(EBIU_SDRRC);
+       r0 = mem_SDRRC;
+       w[p0] = r0.l;
+       ssync;
+
+       p0.l = (EBIU_SDBCTL & 0xFFFF);
+       p0.h = (EBIU_SDBCTL >> 16);     /* 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];
+       BITCLR (R0, 24);
+       p0.h = hi(EBIU_SDSTAT);
+       p0.l = lo(EBIU_SDSTAT);
+       r2.l = w[p0];
+       cc = bittst(r2,3);
+       if !cc jump .Lskip;
+       NOP;
+       BITSET (R0, 23);
+.Lskip:
+       [P2] = R0;
+       SSYNC;
+
+       R0.L = lo(mem_SDGCTL);
+       R0.H = hi(mem_SDGCTL);
+       R1 = [p2];
+       R1 = R1 | R0;
+       [P2] = R1;
+       SSYNC;
+
+       p0.h = hi(SIC_IWR);
+       p0.l = lo(SIC_IWR);
+       r0.l = lo(IWR_ENABLE_ALL);
+       r0.h = hi(IWR_ENABLE_ALL);
+       [p0] = r0;
+       SSYNC;
+
+       RTS;
+#endif /* CONFIG_BFIN_KERNEL_CLOCK */
+
+ENTRY(_bfin_reset)
+       /* No more interrupts to be handled*/
+       CLI R6;
+       SSYNC;
+
+#if defined(CONFIG_MTD_M25P80)
+/*
+ * The following code fix the SPI flash reboot issue,
+ * /CS signal of the chip which is using PF10 return to GPIO mode
+ */
+       p0.h = hi(PORTF_FER);
+       p0.l = lo(PORTF_FER);
+       r0.l = 0x0000;
+       w[p0] = r0.l;
+       SSYNC;
+
+/* /CS return to high */
+       p0.h = hi(PORTFIO);
+       p0.l = lo(PORTFIO);
+       r0.l = 0xFFFF;
+       w[p0] = r0.l;
+       SSYNC;
+
+/* Delay some time, This is necessary */
+       r1.h = 0;
+       r1.l = 0x400;
+       p1   = r1;
+       lsetup (_delay_lab1,_delay_lab1_end ) lc1 = p1;
+_delay_lab1:
+       r0.h = 0;
+       r0.l = 0x8000;
+       p0   = r0;
+       lsetup (_delay_lab0,_delay_lab0_end ) lc0 = p0;
+_delay_lab0:
+       nop;
+_delay_lab0_end:
+       nop;
+_delay_lab1_end:
+       nop;
+#endif
+
+       /* Clear the bits 13-15 in SWRST if they werent cleared */
+       p0.h = hi(SWRST);
+       p0.l = lo(SWRST);
+       csync;
+       r0.l = w[p0];
+
+       /* Clear the IMASK register */
+       p0.h = hi(IMASK);
+       p0.l = lo(IMASK);
+       r0 = 0x0;
+       [p0] = r0;
+
+       /* Clear the ILAT register */
+       p0.h = hi(ILAT);
+       p0.l = lo(ILAT);
+       r0 = [p0];
+       [p0] = r0;
+       SSYNC;
+
+       /* Disable the WDOG TIMER */
+       p0.h = hi(WDOG_CTL);
+       p0.l = lo(WDOG_CTL);
+       r0.l = 0xAD6;
+       w[p0] = r0.l;
+       SSYNC;
+
+       /* Clear the sticky bit incase it is already set */
+       p0.h = hi(WDOG_CTL);
+       p0.l = lo(WDOG_CTL);
+       r0.l = 0x8AD6;
+       w[p0] = r0.l;
+       SSYNC;
+
+       /* Program the count value */
+       R0.l = 0x100;
+       R0.h = 0x0;
+       P0.h = hi(WDOG_CNT);
+       P0.l = lo(WDOG_CNT);
+       [P0] = R0;
+       SSYNC;
+
+       /* Program WDOG_STAT if necessary */
+       P0.h = hi(WDOG_CTL);
+       P0.l = lo(WDOG_CTL);
+       R0 = W[P0](Z);
+       CC = BITTST(R0,1);
+       if !CC JUMP .LWRITESTAT;
+       CC = BITTST(R0,2);
+       if !CC JUMP .LWRITESTAT;
+       JUMP .LSKIP_WRITE;
+
+.LWRITESTAT:
+       /* When watch dog timer is enabled,
+        * a write to STAT will load the contents of CNT to STAT
+        */
+       R0 = 0x0000(z);
+       P0.h = hi(WDOG_STAT);
+       P0.l = lo(WDOG_STAT)
+       [P0] = R0;
+       SSYNC;
+
+.LSKIP_WRITE:
+       /* Enable the reset event */
+       P0.h = hi(WDOG_CTL);
+       P0.l = lo(WDOG_CTL);
+       R0 = W[P0](Z);
+       BITCLR(R0,1);
+       BITCLR(R0,2);
+       W[P0] = R0.L;
+       SSYNC;
+       NOP;
+
+       /* Enable the wdog counter */
+       R0 = W[P0](Z);
+       BITCLR(R0,4);
+       W[P0] = R0.L;
+       SSYNC;
+
+       IDLE;
+
+       RTS;
+
+.data
+
+/*
+ * Set up the usable of RAM stuff. Size of RAM is determined then
+ * an initial stack set up at the end.
+ */
+
+.align 4
+__rambase:
+.long   0
+__ramstart:
+.long   0
+__ramend:
+.long   0
diff --git a/arch/blackfin/mach-bf548/ints-priority.c b/arch/blackfin/mach-bf548/ints-priority.c
new file mode 100644 (file)
index 0000000..cb0ebac
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * File:         arch/blackfin/mach-bf537/ints-priority.c
+ * Based on:     arch/blackfin/mach-bf533/ints-priority.c
+ * Author:       Michael Hennerich
+ *
+ * Created:
+ * Description:  Set up the interupt priorities
+ *
+ * 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/module.h>
+#include <linux/irq.h>
+#include <asm/blackfin.h>
+
+void program_IAR(void)
+{
+       /* Program the IAR0 Register with the configured priority */
+       bfin_write_SIC_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
+                           ((CONFIG_IRQ_DMAC0_ERR - 7) << IRQ_DMAC0_ERR_POS) |
+                           ((CONFIG_IRQ_EPPI0_ERR - 7) << IRQ_EPPI0_ERR_POS) |
+                           ((CONFIG_IRQ_SPORT0_ERR - 7) << IRQ_SPORT0_ERR_POS) |
+                           ((CONFIG_IRQ_SPORT1_ERR - 7) << IRQ_SPORT1_ERR_POS) |
+                           ((CONFIG_IRQ_SPI0_ERR - 7) << IRQ_SPI0_ERR_POS) |
+                           ((CONFIG_IRQ_UART0_ERR - 7) << IRQ_UART0_ERR_POS) |
+                           ((CONFIG_IRQ_RTC - 7) << IRQ_RTC_POS));
+
+       bfin_write_SIC_IAR1(((CONFIG_IRQ_EPPI0 - 7) << IRQ_EPPI0_POS) |
+                           ((CONFIG_IRQ_SPORT0_RX - 7) << IRQ_SPORT0_RX_POS) |
+                           ((CONFIG_IRQ_SPORT0_TX - 7) << IRQ_SPORT0_TX_POS) |
+                           ((CONFIG_IRQ_SPORT1_RX - 7) << IRQ_SPORT1_RX_POS) |
+                           ((CONFIG_IRQ_SPORT1_TX - 7) << IRQ_SPORT1_TX_POS) |
+                           ((CONFIG_IRQ_SPI0 - 7) << IRQ_SPI0_POS) |
+                           ((CONFIG_IRQ_UART0_RX - 7) << IRQ_UART0_RX_POS) |
+                           ((CONFIG_IRQ_UART0_TX - 7) << IRQ_UART0_TX_POS));
+
+       bfin_write_SIC_IAR2(((CONFIG_IRQ_TIMER8 - 7) << IRQ_TIMER8_POS) |
+                           ((CONFIG_IRQ_TIMER9 - 7) << IRQ_TIMER9_POS) |
+                           ((CONFIG_IRQ_PINT0 - 7) << IRQ_PINT0_POS) |
+                           ((CONFIG_IRQ_PINT1 - 7) << IRQ_PINT1_POS) |
+                           ((CONFIG_IRQ_MDMAS0 - 7) << IRQ_MDMAS0_POS) |
+                           ((CONFIG_IRQ_MDMAS1 - 7) << IRQ_MDMAS1_POS) |
+                           ((CONFIG_IRQ_WATCHDOG - 7) << IRQ_WATCHDOG_POS));
+
+       bfin_write_SIC_IAR3(((CONFIG_IRQ_DMAC1_ERR - 7) << IRQ_DMAC1_ERR_POS) |
+                           ((CONFIG_IRQ_SPORT2_ERR - 7) << IRQ_SPORT2_ERR_POS) |
+                           ((CONFIG_IRQ_SPORT3_ERR - 7) << IRQ_SPORT3_ERR_POS) |
+                           ((CONFIG_IRQ_MXVR_DATA - 7) << IRQ_MXVR_DATA_POS) |
+                           ((CONFIG_IRQ_SPI1_ERR - 7) << IRQ_SPI1_ERR_POS) |
+                           ((CONFIG_IRQ_SPI2_ERR - 7) << IRQ_SPI2_ERR_POS) |
+                           ((CONFIG_IRQ_UART1_ERR - 7) << IRQ_UART1_ERR_POS) |
+                           ((CONFIG_IRQ_UART2_ERR - 7) << IRQ_UART2_ERR_POS));
+
+       bfin_write_SIC_IAR4(((CONFIG_IRQ_CAN0_ERR - 7) << IRQ_CAN0_ERR_POS) |
+                           ((CONFIG_IRQ_SPORT2_RX - 7) << IRQ_SPORT2_RX_POS) |
+                           ((CONFIG_IRQ_SPORT2_TX - 7) << IRQ_SPORT2_TX_POS) |
+                           ((CONFIG_IRQ_SPORT3_RX - 7) << IRQ_SPORT3_RX_POS) |
+                           ((CONFIG_IRQ_SPORT3_TX - 7) << IRQ_SPORT3_TX_POS) |
+                           ((CONFIG_IRQ_EPPI1 - 7) << IRQ_EPPI1_POS) |
+                           ((CONFIG_IRQ_EPPI2 - 7) << IRQ_EPPI2_POS) |
+                           ((CONFIG_IRQ_SPI1 - 7) << IRQ_SPI1_POS));
+
+       bfin_write_SIC_IAR5(((CONFIG_IRQ_SPI2 - 7) << IRQ_SPI2_POS) |
+                           ((CONFIG_IRQ_UART1_RX - 7) << IRQ_UART1_RX_POS) |
+                           ((CONFIG_IRQ_UART1_TX - 7) << IRQ_UART1_TX_POS) |
+                           ((CONFIG_IRQ_ATAPI_RX - 7) << IRQ_ATAPI_RX_POS) |
+                           ((CONFIG_IRQ_ATAPI_TX - 7) << IRQ_ATAPI_TX_POS) |
+                           ((CONFIG_IRQ_TWI0 - 7) << IRQ_TWI0_POS) |
+                           ((CONFIG_IRQ_TWI1 - 7) << IRQ_TWI1_POS) |
+                           ((CONFIG_IRQ_CAN0_RX - 7) << IRQ_CAN0_RX_POS));
+
+       bfin_write_SIC_IAR6(((CONFIG_IRQ_CAN0_TX - 7) << IRQ_CAN0_TX_POS) |
+                           ((CONFIG_IRQ_MDMAS2 - 7) << IRQ_MDMAS2_POS) |
+                           ((CONFIG_IRQ_MDMAS3 - 7) << IRQ_MDMAS3_POS) |
+                           ((CONFIG_IRQ_MXVR_ERR - 7) << IRQ_MXVR_ERR_POS) |
+                           ((CONFIG_IRQ_MXVR_MSG - 7) << IRQ_MXVR_MSG_POS) |
+                           ((CONFIG_IRQ_MXVR_PKT - 7) << IRQ_MXVR_PKT_POS) |
+                           ((CONFIG_IRQ_EPPI1_ERR - 7) << IRQ_EPPI1_ERR_POS) |
+                           ((CONFIG_IRQ_EPPI2_ERR - 7) << IRQ_EPPI2_ERR_POS));
+
+       bfin_write_SIC_IAR7(((CONFIG_IRQ_UART3_ERR - 7) << IRQ_UART3_ERR_POS) |
+                           ((CONFIG_IRQ_HOST_ERR - 7) << IRQ_HOST_ERR_POS) |
+                           ((CONFIG_IRQ_PIXC_ERR - 7) << IRQ_PIXC_ERR_POS) |
+                           ((CONFIG_IRQ_NFC_ERR - 7) << IRQ_NFC_ERR_POS) |
+                           ((CONFIG_IRQ_ATAPI_ERR - 7) << IRQ_ATAPI_ERR_POS) |
+                           ((CONFIG_IRQ_CAN1_ERR - 7) << IRQ_CAN1_ERR_POS) |
+                           ((CONFIG_IRQ_HS_DMA_ERR - 7) << IRQ_HS_DMA_ERR_POS));
+
+       bfin_write_SIC_IAR8(((CONFIG_IRQ_PIXC_IN0 - 7) << IRQ_PIXC_IN1_POS) |
+                           ((CONFIG_IRQ_PIXC_IN1 - 7) << IRQ_PIXC_IN1_POS) |
+                           ((CONFIG_IRQ_PIXC_OUT - 7) << IRQ_PIXC_OUT_POS) |
+                           ((CONFIG_IRQ_SDH - 7) << IRQ_SDH_POS) |
+                           ((CONFIG_IRQ_CNT - 7) << IRQ_CNT_POS) |
+                           ((CONFIG_IRQ_KEY - 7) << IRQ_KEY_POS) |
+                           ((CONFIG_IRQ_CAN1_RX - 7) << IRQ_CAN1_RX_POS) |
+                           ((CONFIG_IRQ_CAN1_TX - 7) << IRQ_CAN1_TX_POS));
+
+       bfin_write_SIC_IAR9(((CONFIG_IRQ_SDH_MASK0 - 7) << IRQ_SDH_MASK0_POS) |
+                           ((CONFIG_IRQ_SDH_MASK1 - 7) << IRQ_SDH_MASK1_POS) |
+                           ((CONFIG_IRQ_USB_INT0 - 7) << IRQ_USB_INT0_POS) |
+                           ((CONFIG_IRQ_USB_INT1 - 7) << IRQ_USB_INT1_POS) |
+                           ((CONFIG_IRQ_USB_INT2 - 7) << IRQ_USB_INT2_POS) |
+                           ((CONFIG_IRQ_USB_DMA - 7) << IRQ_USB_DMA_POS) |
+                           ((CONFIG_IRQ_OTPSEC - 7) << IRQ_OTPSEC_POS));
+
+       bfin_write_SIC_IAR10(((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+                            ((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS));
+
+       bfin_write_SIC_IAR11(((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
+                            ((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
+                            ((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS) |
+                            ((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+                            ((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
+                            ((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS) |
+                            ((CONFIG_IRQ_PINT2 - 7) << IRQ_PINT2_POS) |
+                            ((CONFIG_IRQ_PINT3 - 7) << IRQ_PINT3_POS));
+
+       SSYNC();
+}
index 57f475a5516140a5a3ae7bb9109f380f06c524ef..f39235a55783b98c9e040ba92f9848f8282037fe 100644 (file)
@@ -4,6 +4,6 @@
 
 extra-y := head.o
 
-obj-y := ints-priority.o
+obj-y := ints-priority.o dma.o
 
 obj-$(CONFIG_BF561_COREB) += coreb.o
index 3dc5c042048cec307c4cb44bc81e09238b9a0108..5b2b544529a19c49a919f0fb2e57f6b55f9c3eb3 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 
 /*
@@ -52,11 +52,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
                .size = 0x00020000,
                .offset = 0,
                .mask_flags = MTD_CAP_ROM
-       },{
+       }, {
                .name = "kernel",
                .size = 0xe0000,
                .offset = 0x20000
-       },{
+       }, {
                .name = "file system",
                .size = 0x700000,
                .offset = 0x00100000,
@@ -186,7 +186,7 @@ static struct resource smc91x_resources[] = {
                .start = 0x28000300,
                .end = 0x28000300 + 16,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PF0,
                .end = IRQ_PF0,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -206,11 +206,11 @@ static struct resource isp1362_hcd_resources[] = {
                .start = 0x24008000,
                .end = 0x24008000,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = 0x24008004,
                .end = 0x24008004,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PF47,
                .end = IRQ_PF47,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -241,25 +241,25 @@ static struct platform_device isp1362_hcd_device = {
 
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 static struct resource bfin_uart_resources[] = {
-        {
-                .start = 0xFFC00400,
-                .end = 0xFFC004FF,
-                .flags = IORESOURCE_MEM,
-        },
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
 };
 
 static struct platform_device bfin_uart_device = {
-        .name = "bfin-uart",
-        .id = 1,
-        .num_resources = ARRAY_SIZE(bfin_uart_resources),
-        .resource = bfin_uart_resources,
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
 };
 #endif
 
 static struct platform_device *cm_bf561_devices[] __initdata = {
 
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
-        &bfin_uart_device,
+       &bfin_uart_device,
 #endif
 
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
index 9720b5c307ab58c82c0d5b55342b3769b959d52c..724191da20a249a8f1f66c60cfba7b190f5f6074 100644 (file)
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
-#include <asm/irq.h>
-#include <asm/bfin5xx_spi.h>
-#include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/bfin5xx_spi.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -45,13 +44,13 @@ char *bfin_board_name = "ADDS-BF561-EZKIT";
 
 #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,
@@ -71,7 +70,7 @@ static struct platform_device *bfin_isp1761_devices[] = {
 
 int __init bfin_isp1761_init(void)
 {
-       unsigned int num_devices=ARRAY_SIZE(bfin_isp1761_devices);
+       unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
 
        printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
        set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
@@ -98,7 +97,7 @@ static struct resource smc91x_resources[] = {
                .start = 0x2C010300,
                .end = 0x2C010300 + 16,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
 
                .start = IRQ_PF9,
                .end = IRQ_PF9,
@@ -116,18 +115,18 @@ static struct platform_device smc91x_device = {
 
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 static struct resource bfin_uart_resources[] = {
-        {
-                .start = 0xFFC00400,
-                .end = 0xFFC004FF,
-                .flags = IORESOURCE_MEM,
-        },
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
 };
 
 static struct platform_device bfin_uart_device = {
-        .name = "bfin-uart",
-        .id = 1,
-        .num_resources = ARRAY_SIZE(bfin_uart_resources),
-        .resource = bfin_uart_resources,
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
 };
 #endif
 
@@ -176,7 +175,7 @@ static struct platform_device *ezkit_devices[] __initdata = {
        &spi_bfin_master_device,
 #endif
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
-        &bfin_uart_device,
+       &bfin_uart_device,
 #endif
 };
 
index 585ecdd2f6a5889c2a1478bcdbc7298d69cb35a1..4dfea5da674c9acf37968a2c4a1d250756ffffe5 100644 (file)
@@ -30,7 +30,7 @@
 
 #include <linux/device.h>
 #include <linux/platform_device.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 
 char *bfin_board_name = "UNKNOWN BOARD";
 
@@ -43,11 +43,11 @@ static struct resource smc91x_resources[] = {
                .start = 0x2C010300,
                .end = 0x2C010300 + 16,
                .flags = IORESOURCE_MEM,
-       },{
+       }, {
                .start = IRQ_PROG_INTB,
                .end = IRQ_PROG_INTB,
                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-       },{
+       }, {
                /*
                 *  denotes the flag pin and is used directly if
                 *  CONFIG_IRQCHIP_DEMUX_GPIO is defined.
index db308c7ccabbf4dd5014b6542bf5dbb23f395c8e..c442eb23db5ea26916156362d7f38392b5d6e946 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <linux/device.h>
 #include <linux/platform_device.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 
 char *bfin_board_name = "Tepla-BF561";
 
@@ -26,11 +26,11 @@ static struct resource smc91x_resources[] = {
                .start  = 0x2C000300,
                .end    = 0x2C000320,
                .flags  = IORESOURCE_MEM,
-       },{
+       }, {
                .start  = IRQ_PROG_INTB,
                .end    = IRQ_PROG_INTB,
                .flags  = IORESOURCE_IRQ|IORESOURCE_IRQ_HIGHLEVEL,
-       },{
+       }, {
                /*
                 *  denotes the flag pin and is used directly if
                 *  CONFIG_IRQCHIP_DEMUX_GPIO is defined.
index b28582fe083cc698637f130bbfa2f0716697a8fa..5d1d21b4c2a74c3528fb2701e868ae030ca637df 100644 (file)
@@ -32,8 +32,8 @@
 #include <linux/device.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/uaccess.h>
 #include <asm/dma.h>
-#include <asm/uaccess.h>
 
 #define MODULE_VER             "v0.1"
 
@@ -202,7 +202,7 @@ static int coreb_open(struct inode *inode, struct file *file)
        spin_unlock_irq(&coreb_lock);
        return 0;
 
     out_busy:
+ out_busy:
        spin_unlock_irq(&coreb_lock);
        return -EBUSY;
 }
@@ -365,19 +365,19 @@ int __init bf561_coreb_init(void)
        printk(KERN_INFO "BF561 Core B driver %s initialized.\n", MODULE_VER);
        return 0;
 
     release_dma_src:
+ release_dma_src:
        free_dma(CH_MEM_STREAM2_SRC);
     release_dma_dest:
+ release_dma_dest:
        free_dma(CH_MEM_STREAM2_DEST);
     release_data_a_sram:
+ release_data_a_sram:
        release_mem_region(0xff400000, 0x8000);
     release_data_b_sram:
+ release_data_b_sram:
        release_mem_region(0xff500000, 0x8000);
     release_instruction_b_sram:
+ release_instruction_b_sram:
        release_mem_region(0xff610000, 0x4000);
     release_instruction_a_sram:
+ release_instruction_a_sram:
        release_mem_region(0xff600000, 0x4000);
     exit:
+ exit:
        return -ENOMEM;
 }
 
diff --git a/arch/blackfin/mach-bf561/dma.c b/arch/blackfin/mach-bf561/dma.c
new file mode 100644 (file)
index 0000000..89c65bb
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * File:         arch/blackfin/mach-bf561/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ *               Copyright 2004-2007 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 <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+       (struct dma_register *) DMA1_0_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_1_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_2_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_3_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_4_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_5_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_6_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_7_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_8_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_9_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_10_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_11_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_0_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_1_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_2_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_3_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_4_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_5_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_6_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_7_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_8_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_9_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_10_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_11_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA1_D0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA1_S0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA1_D1_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA1_S1_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA2_D0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA2_S0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA2_D1_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA2_S1_NEXT_DESC_PTR,
+       (struct dma_register *) IMDMA_D0_NEXT_DESC_PTR,
+       (struct dma_register *) IMDMA_S0_NEXT_DESC_PTR,
+       (struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
+       (struct dma_register *) IMDMA_S1_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+       int ret_irq = -1;
+
+       switch (channel) {
+       case CH_PPI0:
+               ret_irq = IRQ_PPI0;
+               break;
+       case CH_PPI1:
+               ret_irq = IRQ_PPI1;
+               break;
+       case CH_SPORT0_RX:
+               ret_irq = IRQ_SPORT0_RX;
+               break;
+       case CH_SPORT0_TX:
+               ret_irq = IRQ_SPORT0_TX;
+               break;
+       case CH_SPORT1_RX:
+               ret_irq = IRQ_SPORT1_RX;
+               break;
+       case CH_SPORT1_TX:
+               ret_irq = IRQ_SPORT1_TX;
+               break;
+       case CH_SPI:
+               ret_irq = IRQ_SPI;
+               break;
+       case CH_UART_RX:
+               ret_irq = IRQ_UART_RX;
+               break;
+       case CH_UART_TX:
+               ret_irq = IRQ_UART_TX;
+               break;
+
+       case CH_MEM_STREAM0_SRC:
+       case CH_MEM_STREAM0_DEST:
+               ret_irq = IRQ_MEM_DMA0;
+               break;
+       case CH_MEM_STREAM1_SRC:
+       case CH_MEM_STREAM1_DEST:
+               ret_irq = IRQ_MEM_DMA1;
+               break;
+       case CH_MEM_STREAM2_SRC:
+       case CH_MEM_STREAM2_DEST:
+               ret_irq = IRQ_MEM_DMA2;
+               break;
+       case CH_MEM_STREAM3_SRC:
+       case CH_MEM_STREAM3_DEST:
+               ret_irq = IRQ_MEM_DMA3;
+               break;
+
+       case CH_IMEM_STREAM0_SRC:
+       case CH_IMEM_STREAM0_DEST:
+               ret_irq = IRQ_IMEM_DMA0;
+               break;
+       case CH_IMEM_STREAM1_SRC:
+       case CH_IMEM_STREAM1_DEST:
+               ret_irq = IRQ_IMEM_DMA1;
+               break;
+       }
+       return ret_irq;
+}
index 31cbc75c85cfdac9507445bc873f0e158e6008a8..2f08bcb2dded5158cd0270011ebab21415390496 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/blackfin.h>
+#include <asm/trace.h>
+
 #if CONFIG_BFIN_KERNEL_CLOCK
 #include <asm/mach/mem_init.h>
 #endif
@@ -93,6 +95,10 @@ ENTRY(__start)
        M2 = r0;
        M3 = r0;
 
+       trace_buffer_start(p0,r0);
+       P0 = R1;
+       R0 = R1;
+
        /* Turn off the icache */
        p0.l = (IMEM_CONTROL & 0xFFFF);
        p0.h = (IMEM_CONTROL >> 16);
index 86e3b0ee93f426994498c330210e2232939b488a..09b541b0f7c20c284cb1d549e88a205b82b97d06 100644 (file)
@@ -28,8 +28,8 @@
  */
 
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
 
 void program_IAR(void)
 {
index d3a49073d19615c18dae78078f6f08563893f4ee..0279ede70392fb40d0403044eff8bdd8fd487791 100644 (file)
@@ -4,9 +4,9 @@
 
 obj-y := \
        cache.o cacheinit.o cplbhdlr.o cplbmgr.o entry.o \
-       interrupt.o lock.o dpmc.o irqpanic.o
+       interrupt.o lock.o irqpanic.o
 
 obj-$(CONFIG_CPLB_INFO)          += cplbinfo.o
 obj-$(CONFIG_BFIN_SINGLE_CORE)   += ints-priority-sc.o
 obj-$(CONFIG_BFIN_DUAL_CORE)     += ints-priority-dc.o
-obj-$(CONFIG_PM)                 += pm.o
+obj-$(CONFIG_PM)                 += pm.o dpmc.o
index 7924a90d9658ef900d04aa390ec9f13a514b68fb..9d475623b7243f2069528de67cc291cda01ae9fb 100644 (file)
 
 .text
 
+#ifdef ANOMALY_05000125
 #if defined(CONFIG_BLKFIN_CACHE)
-ENTRY(_bfin_icache_init)
+ENTRY(_bfin_write_IMEM_CONTROL)
 
-       /* Initialize Instruction CPLBS */
-
-       I0.L = (ICPLB_ADDR0 & 0xFFFF);
-       I0.H = (ICPLB_ADDR0 >> 16);
-
-       I1.L = (ICPLB_DATA0 & 0xFFFF);
-       I1.H = (ICPLB_DATA0 >> 16);
-
-       I2.L = _icplb_table;
-       I2.H = _icplb_table;
-
-       r1 = -1;        /* end point comparison */
-       r3 = 15;        /* max counter */
-
-/* read entries from table */
-
-.Lread_iaddr:
-       R0 = [I2++];
-       CC = R0 == R1;
-       IF CC JUMP .Lidone;
-       [I0++] = R0;
-
-.Lread_idata:
-       R2 = [I2++];
-       [I1++] = R2;
-       R3 = R3 + R1;
-       CC = R3 == R1;
-       IF !CC JUMP .Lread_iaddr;
-
-.Lidone:
        /* Enable Instruction Cache */
        P0.l = (IMEM_CONTROL & 0xFFFF);
        P0.h = (IMEM_CONTROL >> 16);
-       R1 = [P0];
-       R0 = (IMC | ENICPLB);
-       R0 = R0 | R1;
 
        /* Anomaly 05000125 */
-       CLI R2;
+       CLI R1;
        SSYNC;          /* SSYNC required before writing to IMEM_CONTROL. */
        .align 8;
        [P0] = R0;
        SSYNC;
-       STI R2;
+       STI R1;
        RTS;
 
-ENDPROC(_bfin_icache_init)
+ENDPROC(_bfin_write_IMEM_CONTROL)
 #endif
 
 #if defined(CONFIG_BLKFIN_DCACHE)
-ENTRY(_bfin_dcache_init)
-
-       /* Initialize Data CPLBS */
-
-       I0.L = (DCPLB_ADDR0 & 0xFFFF);
-       I0.H = (DCPLB_ADDR0 >> 16);
-
-       I1.L = (DCPLB_DATA0 & 0xFFFF);
-       I1.H = (DCPLB_DATA0 >> 16);
-
-       I2.L = _dcplb_table;
-       I2.H = _dcplb_table;
-
-       R1 = -1;        /* end point comparison */
-       R3 = 15;        /* max counter */
-
-       /* read entries from table */
-.Lread_daddr:
-       R0 = [I2++];
-       cc = R0 == R1;
-       IF CC JUMP .Lddone;
-       [I0++] = R0;
-
-.Lread_ddata:
-       R2 = [I2++];
-       [I1++] = R2;
-       R3 = R3 + R1;
-       CC = R3 == R1;
-       IF !CC JUMP .Lread_daddr;
-.Lddone:
-       P0.L = (DMEM_CONTROL & 0xFFFF);
-       P0.H = (DMEM_CONTROL >> 16);
-       R1 = [P0];
-
-       R0 = DMEM_CNTR;
-
-       R0 = R0 | R1;
-       /* Anomaly 05000125 */
-       CLI R2;
+ENTRY(_bfin_write_DMEM_CONTROL)
+       CLI R1;
        SSYNC;          /* SSYNC required before writing to DMEM_CONTROL. */
        .align 8;
        [P0] = R0;
        SSYNC;
-       STI R2;
+       STI R1;
        RTS;
 
-ENDPROC(_bfin_dcache_init)
+ENDPROC(_bfin_write_DMEM_CONTROL)
+#endif
+
 #endif
index caa9623e6bd6d578903e8411f6c607dcd8789779..785ca981697105973a8079fde7ecddde7179274e 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
+#include <linux/uaccess.h>
 
 #include <asm/current.h>
-#include <asm/uaccess.h>
 #include <asm/system.h>
-
 #include <asm/cplb.h>
 #include <asm/blackfin.h>
 
@@ -92,8 +91,7 @@ static char *cplb_print_entry(char *buf, int type)
        } else
                buf += sprintf(buf, "Data CPLB entry:\n");
 
-       buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\
-\tiCount\toCount\n");
+       buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\n\tiCount\toCount\n");
 
        while (*p_addr != 0xffffffff) {
                entry = cplb_find_entry(cplb_addr, cplb_data, *p_addr, *p_data);
@@ -144,8 +142,7 @@ static int cplbinfo_proc_output(char *buf)
 
        p = buf;
 
-       p += sprintf(p,
-                    "------------------ CPLB Information ------------------\n\n");
+       p += sprintf(p, "------------------ CPLB Information ------------------\n\n");
 
        if (bfin_read_IMEM_CONTROL() & ENICPLB)
                p = cplb_print_entry(p, CPLB_I);
@@ -191,9 +188,9 @@ static int __init cplbinfo_init(void)
 {
        struct proc_dir_entry *entry;
 
-       if ((entry = create_proc_entry("cplbinfo", 0, NULL)) == NULL) {
+       entry = create_proc_entry("cplbinfo", 0, NULL);
+       if (!entry)
                return -ENOMEM;
-       }
 
        entry->read_proc = cplbinfo_read_proc;
        entry->write_proc = cplbinfo_write_proc;
index 40045b1386ad888d608fd80d02de1dbb5341ecd8..d61bba98fb548b8baf63980e11aca302902419d4 100644 (file)
 
 
 #include <linux/linkage.h>
+#include <linux/unistd.h>
 #include <asm/blackfin.h>
-#include <asm/unistd.h>
 #include <asm/errno.h>
 #include <asm/thread_info.h>  /* TIF_NEED_RESCHED */
 #include <asm/asm-offsets.h>
+#include <asm/trace.h>
 
 #include <asm/mach-common/context.S>
 
-#ifdef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
-       /*
-        * TODO: this should be proper save/restore, but for now
-        * we'll just cheat and use 0x1/0x13
-        */
-# define DEBUG_START_HWTRACE \
-       P5.l = LO(TBUFCTL); \
-       P5.h = HI(TBUFCTL); \
-       R7 = 0x13; \
-       [P5] = R7;
-# define DEBUG_STOP_HWTRACE \
-       P5.l = LO(TBUFCTL); \
-       P5.h = HI(TBUFCTL); \
-       R7 = 0x01; \
-       [P5] = R7;
-#else
-# define DEBUG_START_HWTRACE
-# define DEBUG_STOP_HWTRACE
-#endif
-
 #ifdef CONFIG_EXCPT_IRQ_SYSC_L1
 .section .l1.text
 #else
@@ -110,25 +91,14 @@ ENTRY(_ex_icplb)
        ASTAT = [sp++];
        SAVE_ALL_SYS
        call __cplb_hdr;
-       DEBUG_START_HWTRACE
+       DEBUG_START_HWTRACE(p5, r7)
        RESTORE_ALL_SYS
        SP = RETN;
        rtx;
 ENDPROC(_ex_icplb)
 
-ENTRY(_ex_spinlock)
-       /* Transform this into a syscall - twiddle the syscall vector.  */
-       p5.l = lo(EVT15);
-       p5.h = hi(EVT15);
-       r7.l = _spinlock_bh;
-       r7.h = _spinlock_bh;
-       [p5] = r7;
-       csync;
-       /* Fall through.  */
-ENDPROC(_ex_spinlock)
-
 ENTRY(_ex_syscall)
-       DEBUG_START_HWTRACE
+       DEBUG_START_HWTRACE(p5, r7)
        (R7:6,P5:4) = [sp++];
        ASTAT = [sp++];
        raise 15;               /* invoked by TRAP #0, for sys call */
@@ -136,26 +106,6 @@ ENTRY(_ex_syscall)
        rtx
 ENDPROC(_ex_syscall)
 
-ENTRY(_spinlock_bh)
-       SAVE_ALL_SYS
-       /* To end up here, vector 15 was changed - so we have to change it
-        * back.
-        */
-       p0.l = lo(EVT15);
-       p0.h = hi(EVT15);
-       p1.l = _evt_system_call;
-       p1.h = _evt_system_call;
-       [p0] = p1;
-       csync;
-       r0 = [sp + PT_R0];
-       sp += -12;
-       call _sys_bfin_spinlock;
-       sp += 12;
-       [SP + PT_R0] = R0;
-       RESTORE_ALL_SYS
-       rti;
-ENDPROC(_spinlock_bh)
-
 ENTRY(_ex_soft_bp)
        r7 = retx;
        r7 += -2;
@@ -186,7 +136,7 @@ ENTRY(_ex_single_step)
        if !cc jump _ex_trap_c;
 
 _return_from_exception:
-       DEBUG_START_HWTRACE
+       DEBUG_START_HWTRACE(p5, r7)
 #ifdef ANOMALY_05000257
        R7=LC0;
        LC0=R7;
@@ -208,7 +158,7 @@ ENTRY(_handle_bad_cplb)
         * need to make a CPLB exception look like a normal exception
         */
 
-       DEBUG_START_HWTRACE
+       DEBUG_START_HWTRACE(p5, r7)
        RESTORE_ALL_SYS
        [--sp] = ASTAT;
        [--sp] = (R7:6, P5:4);
@@ -251,7 +201,7 @@ ENTRY(_ex_trap_c)
        R6 = SEQSTAT;
        [P5] = R6;
 
-       DEBUG_START_HWTRACE
+       DEBUG_START_HWTRACE(p5, r7)
        (R7:6,P5:4) = [sp++];
        ASTAT = [sp++];
        SP = RETN;
@@ -335,7 +285,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
        /* Try to deal with syscalls quickly.  */
        [--sp] = ASTAT;
        [--sp] = (R7:6, P5:4);
-       DEBUG_STOP_HWTRACE
+       DEBUG_STOP_HWTRACE(p5, r7)
        r7 = SEQSTAT;           /* reason code is in bit 5:0 */
        r6.l = lo(SEQSTAT_EXCAUSE);
        r6.h = hi(SEQSTAT_EXCAUSE);
@@ -741,6 +691,10 @@ _schedule_and_signal_from_int:
        r0 = [p0];
        sti r0;
 
+       r0 = sp;
+       sp += -12;
+       call _finish_atomic_sections;
+       sp += 12;
        jump.s .Lresume_userspace;
 
 _schedule_and_signal:
@@ -790,14 +744,14 @@ ENDPROC(_init_exception_buff)
 ALIGN
 _extable:
        /* entry for each EXCAUSE[5:0]
-        * This table bmust be in sync with the table in ./kernel/traps.c
+        * This table must be in sync with the table in ./kernel/traps.c
         * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined
         */
        .long _ex_syscall;      /* 0x00 - User Defined - Linux Syscall */
        .long _ex_soft_bp       /* 0x01 - User Defined - Software breakpoint */
        .long _ex_trap_c        /* 0x02 - User Defined */
-       .long _ex_trap_c        /* 0x03 - User Defined  - Atomic test and set service */
-       .long _ex_spinlock      /* 0x04 - User Defined */
+       .long _ex_trap_c        /* 0x03 - User Defined - userspace stack overflow */
+       .long _ex_trap_c        /* 0x04 - User Defined */
        .long _ex_trap_c        /* 0x05 - User Defined */
        .long _ex_trap_c        /* 0x06 - User Defined */
        .long _ex_trap_c        /* 0x07 - User Defined */
index 8be548e061bff73a82b98659e500ddadd29abbc2..203e20709163811021e98131d2747b32e189c3a1 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/linkage.h>
 #include <asm/entry.h>
 #include <asm/asm-offsets.h>
+#include <asm/trace.h>
 
 #include <asm/mach-common/context.S>
 
@@ -170,10 +171,9 @@ ENTRY(_evt_ivhw)
        r7.l = W[p5];
 1:
 #endif
-       p0.l = lo(TBUFCTL);
-       p0.h = hi(TBUFCTL);
-       r0 = 1;
-       [p0] = r0;
+
+       trace_buffer_stop(p0, r0);
+
        r0 = IRQ_HWERR;
        r1 = sp;
 
index 80943bbd37c202f8d1a58b8a6d5f3bdc15074ab3..6b9fd03ce8355135b7227b9073d2249690aff766 100644 (file)
@@ -183,7 +183,7 @@ static void bf561_gpio_ack_irq(unsigned int irq)
 {
        u16 gpionr = irq - IRQ_PF0;
 
-       if(gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
+       if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
                set_gpio_data(gpionr, 0);
                SSYNC();
        }
@@ -193,7 +193,7 @@ static void bf561_gpio_mask_ack_irq(unsigned int irq)
 {
        u16 gpionr = irq - IRQ_PF0;
 
-       if(gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
+       if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
                set_gpio_data(gpionr, 0);
                SSYNC();
        }
@@ -222,7 +222,7 @@ static unsigned int bf561_gpio_irq_startup(unsigned int irq)
        if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
 
                ret = gpio_request(gpionr, NULL);
-               if(ret)
+               if (ret)
                        return ret;
 
        }
@@ -262,7 +262,7 @@ static int bf561_gpio_irq_type(unsigned int irq, unsigned int type)
                if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
 
                        ret = gpio_request(gpionr, NULL);
-                       if(ret)
+                       if (ret)
                                return ret;
 
                }
@@ -371,6 +371,9 @@ int __init init_arch_irq(void)
        bfin_write_SICA_IMASK1(SIC_UNMASK_ALL);
        SSYNC();
 
+       bfin_write_SICA_IWR0(IWR_ENABLE_ALL);
+       bfin_write_SICA_IWR1(IWR_ENABLE_ALL);
+
        local_irq_disable();
 
        init_exception_buff();
@@ -393,7 +396,7 @@ int __init init_arch_irq(void)
        bfin_write_EVT15(evt_system_call);
        CSYNC();
 
-       for (irq = 0; irq < SYS_IRQS; irq++) {
+       for (irq = 0; irq <= SYS_IRQS; irq++) {
                if (irq <= IRQ_CORETMR)
                        set_irq_chip(irq, &bf561_core_irqchip);
                else
index 2cfc7d5aec5cafba6846f4a4cc9bb489e726fe7e..28a878c3577a00d78e280b137e09be5124c4351d 100644 (file)
@@ -13,7 +13,7 @@
  *               2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
  *               2003 Metrowerks/Motorola
  *               2003 Bas Vermeulen <bas@buyways.nl>
- *               Copyright 2004-2006 Analog Devices Inc.
+ *               Copyright 2004-2007 Analog Devices Inc.
  *
  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  *
@@ -65,9 +65,9 @@ atomic_t num_spurious;
 
 struct ivgx {
        /* irq number for request_irq, available in mach-bf533/irq.h */
-       int irqno;
+       unsigned int irqno;
        /* corresponding bit in the SIC_ISR register */
-       int isrflag;
+       unsigned int isrflag;
 } ivg_table[NR_PERI_INTS];
 
 struct ivg_slice {
@@ -88,17 +88,16 @@ static void __init search_IAR(void)
        for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) {
                int irqn;
 
-               ivg7_13[ivg].istop = ivg7_13[ivg].ifirst =
-                   &ivg_table[irq_pos];
+               ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos];
 
                for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
                        int iar_shift = (irqn & 7) * 4;
                        if (ivg ==
                            (0xf &
-                            bfin_read32((unsigned long *) SIC_IAR0 +
+                            bfin_read32((unsigned long *)SIC_IAR0 +
                                         (irqn >> 3)) >> iar_shift)) {
                                ivg_table[irq_pos].irqno = IVG7 + irqn;
-                               ivg_table[irq_pos].isrflag = 1 << irqn;
+                               ivg_table[irq_pos].isrflag = 1 << (irqn % 32);
                                ivg7_13[ivg].istop++;
                                irq_pos++;
                        }
@@ -141,15 +140,31 @@ static void bfin_core_unmask_irq(unsigned int irq)
 
 static void bfin_internal_mask_irq(unsigned int irq)
 {
+#ifndef CONFIG_BF54x
        bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
                             ~(1 << (irq - (IRQ_CORETMR + 1))));
+#else
+       unsigned mask_bank, mask_bit;
+       mask_bank = (irq - (IRQ_CORETMR + 1)) / 32;
+       mask_bit = (irq - (IRQ_CORETMR + 1)) % 32;
+       bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
+                            ~(1 << mask_bit));
+#endif
        SSYNC();
 }
 
 static void bfin_internal_unmask_irq(unsigned int irq)
 {
+#ifndef CONFIG_BF54x
        bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
                             (1 << (irq - (IRQ_CORETMR + 1))));
+#else
+       unsigned mask_bank, mask_bit;
+       mask_bank = (irq - (IRQ_CORETMR + 1)) / 32;
+       mask_bit = (irq - (IRQ_CORETMR + 1)) % 32;
+       bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) |
+                            (1 << mask_bit));
+#endif
        SSYNC();
 }
 
@@ -206,7 +221,7 @@ static struct irq_chip bfin_generic_error_irqchip = {
 };
 
 static void bfin_demux_error_irq(unsigned int int_err_irq,
-                                 struct irq_desc *intb_desc)
+                                struct irq_desc *intb_desc)
 {
        int irq = 0;
 
@@ -270,8 +285,8 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
                        }
 
                        pr_debug("IRQ %d:"
-                               " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n",
-                               irq);
+                                " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n",
+                                irq);
                }
        } else
                printk(KERN_ERR
@@ -279,11 +294,10 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
                       " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
                       __FUNCTION__, __FILE__, __LINE__);
 
-
 }
 #endif                         /* BF537_GENERIC_ERROR_INT_DEMUX */
 
-#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#if defined(CONFIG_IRQCHIP_DEMUX_GPIO) && !defined(CONFIG_BF54x)
 
 static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
 static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
@@ -361,8 +375,7 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
        }
 
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
-                   IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-       {
+                   IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
                if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
                        ret = gpio_request(gpionr, NULL);
                        if (ret)
@@ -407,7 +420,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
        return 0;
 }
 
-
 static struct irq_chip bfin_gpio_irqchip = {
        .ack = bfin_gpio_ack_irq,
        .mask = bfin_gpio_mask_irq,
@@ -419,20 +431,20 @@ static struct irq_chip bfin_gpio_irqchip = {
 };
 
 static void bfin_demux_gpio_irq(unsigned int intb_irq,
-                                struct irq_desc *intb_desc)
+                               struct irq_desc *intb_desc)
 {
        u16 i;
+       struct irq_desc *desc;
 
-       for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=16) {
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i += 16) {
                int irq = IRQ_PF0 + i;
                int flag_d = get_gpiop_data(i);
                int mask =
-                       flag_d & (gpio_enabled[gpio_bank(i)] &
-                             get_gpiop_maska(i));
+                   flag_d & (gpio_enabled[gpio_bank(i)] & get_gpiop_maska(i));
 
                while (mask) {
                        if (mask & 1) {
-                               struct irq_desc *desc = irq_desc + irq;
+                               desc = irq_desc + irq;
                                desc->handle_irq(irq, desc);
                        }
                        irq++;
@@ -441,6 +453,264 @@ static void bfin_demux_gpio_irq(unsigned int intb_irq,
        }
 }
 
+#else                          /* CONFIG_IRQCHIP_DEMUX_GPIO */
+
+#define NR_PINT_SYS_IRQS       4
+#define NR_PINT_BITS           32
+#define NR_PINTS               160
+#define IRQ_NOT_AVAIL          0xFF
+
+#define PINT_2_BANK(x)         ((x) >> 5)
+#define PINT_2_BIT(x)          ((x) & 0x1F)
+#define PINT_BIT(x)            (1 << (PINT_2_BIT(x)))
+
+static unsigned char irq2pint_lut[NR_PINTS];
+static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];
+
+struct pin_int_t {
+       unsigned int mask_set;
+       unsigned int mask_clear;
+       unsigned int request;
+       unsigned int assign;
+       unsigned int edge_set;
+       unsigned int edge_clear;
+       unsigned int invert_set;
+       unsigned int invert_clear;
+       unsigned int pinstate;
+       unsigned int latch;
+};
+
+static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
+       (struct pin_int_t *)PINT0_MASK_SET,
+       (struct pin_int_t *)PINT1_MASK_SET,
+       (struct pin_int_t *)PINT2_MASK_SET,
+       (struct pin_int_t *)PINT3_MASK_SET,
+};
+
+unsigned short get_irq_base(u8 bank, u8 bmap)
+{
+
+       u16 irq_base;
+
+       if (bank < 2) {         /*PA-PB */
+               irq_base = IRQ_PA0 + bmap * 16;
+       } else {                /*PC-PJ */
+               irq_base = IRQ_PC0 + bmap * 16;
+       }
+
+       return irq_base;
+
+}
+
+       /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
+void init_pint_lut(void)
+{
+       u16 bank, bit, irq_base, bit_pos;
+       u32 pint_assign;
+       u8 bmap;
+
+       memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut));
+
+       for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) {
+
+               pint_assign = pint[bank]->assign;
+
+               for (bit = 0; bit < NR_PINT_BITS; bit++) {
+
+                       bmap = (pint_assign >> ((bit / 8) * 8)) & 0xFF;
+
+                       irq_base = get_irq_base(bank, bmap);
+
+                       irq_base += (bit % 8) + ((bit / 8) & 1 ? 8 : 0);
+                       bit_pos = bit + bank * NR_PINT_BITS;
+
+                       pint2irq_lut[bit_pos] = irq_base - SYS_IRQS;
+                       irq2pint_lut[irq_base - SYS_IRQS] = bit_pos;
+
+               }
+
+       }
+
+}
+
+static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+static void bfin_gpio_ack_irq(unsigned int irq)
+{
+       u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+
+       pint[PINT_2_BANK(pint_val)]->request = PINT_BIT(pint_val);
+       SSYNC();
+}
+
+static void bfin_gpio_mask_ack_irq(unsigned int irq)
+{
+       u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+       u32 pintbit = PINT_BIT(pint_val);
+       u8 bank = PINT_2_BANK(pint_val);
+
+       pint[bank]->request = pintbit;
+       pint[bank]->mask_clear = pintbit;
+       SSYNC();
+}
+
+static void bfin_gpio_mask_irq(unsigned int irq)
+{
+       u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+
+       pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val);
+       SSYNC();
+}
+
+static void bfin_gpio_unmask_irq(unsigned int irq)
+{
+       u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+       u32 pintbit = PINT_BIT(pint_val);
+       u8 bank = PINT_2_BANK(pint_val);
+
+       pint[bank]->request = pintbit;
+       pint[bank]->mask_set = pintbit;
+       SSYNC();
+}
+
+static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+{
+       unsigned int ret;
+       u16 gpionr = irq - IRQ_PA0;
+       u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+
+       if (pint_val == IRQ_NOT_AVAIL)
+               return -ENODEV;
+
+       if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+               ret = gpio_request(gpionr, NULL);
+               if (ret)
+                       return ret;
+       }
+
+       gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+       bfin_gpio_unmask_irq(irq);
+
+       return ret;
+}
+
+static void bfin_gpio_irq_shutdown(unsigned int irq)
+{
+       bfin_gpio_mask_irq(irq);
+       gpio_free(irq - IRQ_PA0);
+       gpio_enabled[gpio_bank(irq - IRQ_PA0)] &= ~gpio_bit(irq - IRQ_PA0);
+}
+
+static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+{
+
+       unsigned int ret;
+       u16 gpionr = irq - IRQ_PA0;
+       u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+       u32 pintbit = PINT_BIT(pint_val);
+       u8 bank = PINT_2_BANK(pint_val);
+
+       if (pint_val == IRQ_NOT_AVAIL)
+               return -ENODEV;
+
+       if (type == IRQ_TYPE_PROBE) {
+               /* only probe unenabled GPIO interrupt lines */
+               if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))
+                       return 0;
+               type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+       }
+
+       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
+                   IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+               if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+                       ret = gpio_request(gpionr, NULL);
+                       if (ret)
+                               return ret;
+               }
+
+               gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+       } else {
+               gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+               return 0;
+       }
+
+       gpio_direction_input(gpionr);
+
+       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+               pint[bank]->edge_set = pintbit;
+       } else {
+               pint[bank]->edge_clear = pintbit;
+       }
+
+       if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
+               pint[bank]->invert_set = pintbit;       /* low or falling edge denoted by one */
+       else
+               pint[bank]->invert_set = pintbit;       /* high or rising edge denoted by zero */
+
+       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+               pint[bank]->invert_set = pintbit;
+       else
+               pint[bank]->invert_set = pintbit;
+
+       SSYNC();
+
+       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+               set_irq_handler(irq, handle_edge_irq);
+       else
+               set_irq_handler(irq, handle_level_irq);
+
+       return 0;
+}
+
+static struct irq_chip bfin_gpio_irqchip = {
+       .ack = bfin_gpio_ack_irq,
+       .mask = bfin_gpio_mask_irq,
+       .mask_ack = bfin_gpio_mask_ack_irq,
+       .unmask = bfin_gpio_unmask_irq,
+       .set_type = bfin_gpio_irq_type,
+       .startup = bfin_gpio_irq_startup,
+       .shutdown = bfin_gpio_irq_shutdown
+};
+
+static void bfin_demux_gpio_irq(unsigned int intb_irq,
+                               struct irq_desc *intb_desc)
+{
+       u8 bank, pint_val;
+       u32 request, irq;
+       struct irq_desc *desc;
+
+       switch (intb_irq) {
+       case IRQ_PINT0:
+               bank = 0;
+               break;
+       case IRQ_PINT2:
+               bank = 2;
+               break;
+       case IRQ_PINT3:
+               bank = 3;
+               break;
+       case IRQ_PINT1:
+               bank = 1;
+               break;
+       default:
+               return;
+       }
+
+       pint_val = bank * NR_PINT_BITS;
+
+       request = pint[bank]->request;
+
+       while (request) {
+               if (request & 1) {
+                       irq = pint2irq_lut[pint_val] + SYS_IRQS;
+                       desc = irq_desc + irq;
+                       desc->handle_irq(irq, desc);
+               }
+               pint_val++;
+               request >>= 1;
+       }
+
+}
 #endif                         /* CONFIG_IRQCHIP_DEMUX_GPIO */
 
 /*
@@ -452,7 +722,18 @@ int __init init_arch_irq(void)
        int irq;
        unsigned long ilat = 0;
        /*  Disable all the peripheral intrs  - page 4-29 HW Ref manual */
+#ifdef CONFIG_BF54x
+       bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
+       bfin_write_SIC_IMASK1(SIC_UNMASK_ALL);
+       bfin_write_SIC_IMASK2(SIC_UNMASK_ALL);
+       bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
+       bfin_write_SIC_IWR1(IWR_ENABLE_ALL);
+       bfin_write_SIC_IWR2(IWR_ENABLE_ALL);
+#else
        bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
+       bfin_write_SIC_IWR(IWR_ENABLE_ALL);
+#endif
+
        SSYNC();
 
        local_irq_disable();
@@ -475,7 +756,18 @@ int __init init_arch_irq(void)
        bfin_write_EVT15(evt_system_call);
        CSYNC();
 
-       for (irq = 0; irq < SYS_IRQS; irq++) {
+#if defined(CONFIG_IRQCHIP_DEMUX_GPIO) && defined(CONFIG_BF54x)
+#ifdef CONFIG_PINTx_REASSIGN
+       pint[0]->assign = CONFIG_PINT0_ASSIGN;
+       pint[1]->assign = CONFIG_PINT1_ASSIGN;
+       pint[2]->assign = CONFIG_PINT2_ASSIGN;
+       pint[3]->assign = CONFIG_PINT3_ASSIGN;
+#endif
+       /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
+       init_pint_lut();
+#endif
+
+       for (irq = 0; irq <= SYS_IRQS; irq++) {
                if (irq <= IRQ_CORETMR)
                        set_irq_chip(irq, &bfin_core_irqchip);
                else
@@ -484,20 +776,42 @@ int __init init_arch_irq(void)
                if (irq != IRQ_GENERIC_ERROR) {
 #endif
 
+                       switch (irq) {
 #ifdef CONFIG_IRQCHIP_DEMUX_GPIO
-                       if ((irq != IRQ_PROG_INTA) /*PORT F & G MASK_A Interrupt*/
-# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
-                               && (irq != IRQ_MAC_RX) /*PORT H MASK_A Interrupt*/
-# endif
-                           ) {
+#ifndef CONFIG_BF54x
+                       case IRQ_PROG_INTA:
+                               set_irq_chained_handler(irq,
+                                                       bfin_demux_gpio_irq);
+                               break;
+#if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
+                       case IRQ_MAC_RX:
+                               set_irq_chained_handler(irq,
+                                                       bfin_demux_gpio_irq);
+                               break;
 #endif
-                               set_irq_handler(irq, handle_simple_irq);
-#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
-                       } else {
+#else
+                       case IRQ_PINT0:
                                set_irq_chained_handler(irq,
                                                        bfin_demux_gpio_irq);
-                       }
+                               break;
+                       case IRQ_PINT1:
+                               set_irq_chained_handler(irq,
+                                                       bfin_demux_gpio_irq);
+                               break;
+                       case IRQ_PINT2:
+                               set_irq_chained_handler(irq,
+                                                       bfin_demux_gpio_irq);
+                               break;
+                       case IRQ_PINT3:
+                               set_irq_chained_handler(irq,
+                                                       bfin_demux_gpio_irq);
+                               break;
+#endif                         /*CONFIG_BF54x */
 #endif
+                       default:
+                               set_irq_handler(irq, handle_simple_irq);
+                               break;
+                       }
 
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
                } else {
@@ -513,7 +827,11 @@ int __init init_arch_irq(void)
 #endif
 
 #ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#ifndef CONFIG_BF54x
        for (irq = IRQ_PF0; irq < NR_IRQS; irq++) {
+#else
+       for (irq = IRQ_PA0; irq < NR_IRQS; irq++) {
+#endif
                set_irq_chip(irq, &bfin_gpio_irqchip);
                /* if configured as edge, then will be changed to do_edge_IRQ */
                set_irq_handler(irq, handle_level_irq);
@@ -526,8 +844,7 @@ int __init init_arch_irq(void)
        bfin_write_ILAT(ilat);
        CSYNC();
 
-       printk(KERN_INFO
-              "Configuring Blackfin Priority Driven Interrupts\n");
+       printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");
        /* IMASK=xxx is equivalent to STI xx or irq_flags=xx,
         * local_irq_enable()
         */
@@ -538,14 +855,13 @@ int __init init_arch_irq(void)
        /* Enable interrupts IVG7-15 */
        irq_flags = irq_flags | IMASK_IVG15 |
            IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
-           IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 |
-           IMASK_IVGHW;
+           IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
 
        return 0;
 }
 
 #ifdef CONFIG_DO_IRQ_L1
-void do_irq(int vec, struct pt_regs *fp)__attribute__((l1_text));
+void do_irq(int vec, struct pt_regs *fp) __attribute__((l1_text));
 #endif
 
 void do_irq(int vec, struct pt_regs *fp)
@@ -555,8 +871,24 @@ void do_irq(int vec, struct pt_regs *fp)
        } else {
                struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
                struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
-               unsigned long sic_status;
+#ifdef CONFIG_BF54x
+               unsigned long sic_status[3];
 
+               SSYNC();
+               sic_status[0] = bfin_read_SIC_ISR(0) & bfin_read_SIC_IMASK(0);
+               sic_status[1] = bfin_read_SIC_ISR(1) & bfin_read_SIC_IMASK(1);
+               sic_status[2] = bfin_read_SIC_ISR(2) & bfin_read_SIC_IMASK(2);
+
+               for (;; ivg++) {
+                       if (ivg >= ivg_stop) {
+                               atomic_inc(&num_spurious);
+                               return;
+                       }
+                       if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag)
+                               break;
+               }
+#else
+               unsigned long sic_status;
                SSYNC();
                sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();
 
@@ -567,6 +899,7 @@ void do_irq(int vec, struct pt_regs *fp)
                        } else if (sic_status & ivg->isrflag)
                                break;
                }
+#endif
                vec = ivg->irqno;
        }
        asm_do_IRQ(vec, fp);
index 150ef5d088dcfedcdf0bb1d5a5922582c25c3f08..1772d8d2c1a7c30ea4b885afe794deac6a68481e 100644 (file)
 #include <linux/pm.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 
-#include <asm/io.h>
 #include <asm/dpmc.h>
-#include <asm/irq.h>
 #include <asm/gpio.h>
 
 #ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_H
index 68107924639ecd8bade350354e9a29d2500d939b..16c6169ed01bbe3357931d184d9532e5ac4649ab 100644 (file)
@@ -87,7 +87,7 @@ void __init l1sram_init(void)
               L1_SCRATCH_LENGTH >> 10);
 
        memset(&l1_ssram, 0x00, sizeof(l1_ssram));
-       l1_ssram[0].paddr = (void*)L1_SCRATCH_START;
+       l1_ssram[0].paddr = (void *)L1_SCRATCH_START;
        l1_ssram[0].size = L1_SCRATCH_LENGTH;
        l1_ssram[0].flag = SRAM_SLT_FREE;
 
@@ -126,7 +126,7 @@ 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].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;
 
index 570356dbe02843a144c486e5d4c94d892c076fd8..68459cc052a142ac14df1545c0c3fe86ec88428f 100644 (file)
@@ -29,8 +29,8 @@
 
 #include <linux/swap.h>
 #include <linux/bootmem.h>
+#include <linux/uaccess.h>
 #include <asm/bfin-global.h>
-#include <asm/uaccess.h>
 #include <asm/l1layout.h>
 #include "blackfin_sram.h"
 
@@ -168,42 +168,31 @@ void __init mem_init(void)
        }
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init free_initrd_mem(unsigned long start, unsigned long end)
+static __init void free_init_pages(const char *what, unsigned long begin, unsigned long end)
 {
-       int pages = 0;
-       for (; start < end; start += PAGE_SIZE) {
-               ClearPageReserved(virt_to_page(start));
-               init_page_count(virt_to_page(start));
-               free_page(start);
+       unsigned long addr;
+       /* next to check that the page we free is not a partial page */
+       for (addr = begin; addr + PAGE_SIZE <= end; addr += PAGE_SIZE) {
+               ClearPageReserved(virt_to_page(addr));
+               init_page_count(virt_to_page(addr));
+               free_page(addr);
                totalram_pages++;
-               pages++;
        }
-       printk(KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages);
+       printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void __init free_initrd_mem(unsigned long start, unsigned long end)
+{
+       free_init_pages("initrd memory", start, end);
 }
 #endif
 
 void __init free_initmem(void)
 {
 #ifdef CONFIG_RAMKERNEL
-       unsigned long addr;
-       /*
-        *      the following code should be cool even if these sections
-        *      are not page aligned.
-        */
-       addr = PAGE_ALIGN((unsigned long)(__init_begin));
-       /* next to check that the page we free is not a partial page */
-       for (; addr + PAGE_SIZE < (unsigned long)(__init_end);
-            addr += PAGE_SIZE) {
-               ClearPageReserved(virt_to_page(addr));
-               init_page_count(virt_to_page(addr));
-               free_page(addr);
-               totalram_pages++;
-       }
-       printk(KERN_NOTICE
-              "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
-              (addr - PAGE_ALIGN((long)__init_begin)) >> 10,
-              (int)(PAGE_ALIGN((unsigned long)(__init_begin))),
-              (int)(addr - PAGE_SIZE));
+       free_init_pages("unused kernel memory",
+                       (unsigned long)(&__init_begin),
+                       (unsigned long)(&__init_end));
 #endif
 }
index 009a1700c854fd5b09be02a3ae37d6440a9ea8da..cb8b8d5af34fa450f1c58273d10acf71428eff2b 100644 (file)
 #include <linux/smp.h>
 #include <linux/errno.h>
 #include <linux/mutex.h>
+#include <linux/ptrace.h>
+#include <linux/irq.h>
+#include <linux/io.h>
 
-#include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/io.h>
 
 #include "op_blackfin.h"
 
index b7a20a006b4921cc6d7cbb224412bb8d39c0f83b..872dffe3362360f6eb1e46e4d9d53961d04c359e 100644 (file)
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <asm/ptrace.h>
+#include <linux/ptrace.h>
+#include <linux/irq.h>
+#include <linux/io.h>
 #include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/io.h>
 
 #include "op_blackfin.h"
 
index 8fba16c846c9b6ea3d7711529a647f22c2bc5200..6c6f8606af4ceefcfd0dd0b81b25f9c60835808b 100644 (file)
@@ -31,8 +31,7 @@
 #include <linux/smp.h>
 #include <linux/irq.h>
 #include <linux/oprofile.h>
-
-#include <asm/ptrace.h>
+#include <linux/ptrace.h>
 
 static void enable_sys_timer0()
 {
index 5c95ceb7f1225515ab3ad200a8f1e7a278a2ee18..9cbe76c3aa359763c6650aa4a57d97c16ee5d4e4 100644 (file)
@@ -344,8 +344,8 @@ config X86_CMOV
        depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7)
        default y
 
-config X86_MINIMUM_CPU_MODEL
+config X86_MINIMUM_CPU_FAMILY
        int
-       default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP
-       default "0"
+       default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK
+       default "3"
 
index bfbc32098a4a8ed33237915b9991e96ac001bd75..08678a0a3d191a8a197763bc35202d0c79765b33 100644 (file)
@@ -25,27 +25,56 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
 
 #RAMDISK := -DRAMDISK=512
 
-targets                := vmlinux.bin bootsect bootsect.o \
-                  setup setup.o zImage bzImage
+targets                := vmlinux.bin setup.bin setup.elf zImage bzImage
 subdir-        := compressed
 
+setup-y                += a20.o apm.o cmdline.o copy.o cpu.o cpucheck.o edd.o
+setup-y                += header.o main.o mca.o memory.o pm.o pmjump.o
+setup-y                += printf.o string.o tty.o video.o version.o voyager.o
+
+# The link order of the video-*.o modules can matter.  In particular,
+# video-vga.o *must* be listed first, followed by video-vesa.o.
+# Hardware-specific drivers should follow in the order they should be
+# probed, and video-bios.o should typically be last.
+setup-y                += video-vga.o
+setup-y                += video-vesa.o
+setup-y                += video-bios.o
+
 hostprogs-y    := tools/build
 
 HOSTCFLAGS_build.o := $(LINUXINCLUDE)
 
 # ---------------------------------------------------------------------------
 
+# How to compile the 16-bit code.  Note we always compile for -march=i386,
+# that way we can complain to the user if the CPU is insufficient.
+cflags-i386   := 
+cflags-x86_64 := -m32
+CFLAGS         := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
+                  $(cflags-$(ARCH)) \
+                  -Wall -Wstrict-prototypes \
+                  -march=i386 -mregparm=3 \
+                  -include $(srctree)/$(src)/code16gcc.h \
+                  -fno-strict-aliasing -fomit-frame-pointer \
+                  $(call cc-option, -ffreestanding) \
+                  $(call cc-option, -fno-toplevel-reorder,\
+                       $(call cc-option, -fno-unit-at-a-time)) \
+                  $(call cc-option, -fno-stack-protector) \
+                  $(call cc-option, -mpreferred-stack-boundary=2)
+AFLAGS         := $(CFLAGS) -D__ASSEMBLY__
+
 $(obj)/zImage:  IMAGE_OFFSET := 0x1000
 $(obj)/zImage:  EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK)
 $(obj)/bzImage: IMAGE_OFFSET := 0x100000
+$(obj)/bzImage: EXTRA_CFLAGS := -D__BIG_KERNEL__
 $(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
 $(obj)/bzImage: BUILDFLAGS   := -b
 
 quiet_cmd_image = BUILD   $@
-cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
+cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/setup.bin \
            $(obj)/vmlinux.bin $(ROOT_DEV) > $@
 
-$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
+$(obj)/zImage $(obj)/bzImage: $(obj)/setup.bin \
                              $(obj)/vmlinux.bin $(obj)/tools/build FORCE
        $(call if_changed,image)
        @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
@@ -53,12 +82,17 @@ $(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
 $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
        $(call if_changed,objcopy)
 
-LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
-LDFLAGS_setup   := -Ttext 0x0 -s --oformat binary -e begtext
+SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
 
-$(obj)/setup $(obj)/bootsect: %: %.o FORCE
+LDFLAGS_setup.elf      := -T
+$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
        $(call if_changed,ld)
 
+OBJCOPYFLAGS_setup.bin := -O binary
+
+$(obj)/setup.bin: $(obj)/setup.elf FORCE
+       $(call if_changed,objcopy)
+
 $(obj)/compressed/vmlinux: FORCE
        $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
 
diff --git a/arch/i386/boot/a20.c b/arch/i386/boot/a20.c
new file mode 100644 (file)
index 0000000..31348d0
--- /dev/null
@@ -0,0 +1,161 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/a20.c
+ *
+ * Enable A20 gate (return -1 on failure)
+ */
+
+#include "boot.h"
+
+#define MAX_8042_LOOPS 100000
+
+static int empty_8042(void)
+{
+       u8 status;
+       int loops = MAX_8042_LOOPS;
+
+       while (loops--) {
+               io_delay();
+
+               status = inb(0x64);
+               if (status & 1) {
+                       /* Read and discard input data */
+                       io_delay();
+                       (void)inb(0x60);
+               } else if (!(status & 2)) {
+                       /* Buffers empty, finished! */
+                       return 0;
+               }
+       }
+
+       return -1;
+}
+
+/* Returns nonzero if the A20 line is enabled.  The memory address
+   used as a test is the int $0x80 vector, which should be safe. */
+
+#define A20_TEST_ADDR  (4*0x80)
+#define A20_TEST_SHORT  32
+#define A20_TEST_LONG  2097152 /* 2^21 */
+
+static int a20_test(int loops)
+{
+       int ok = 0;
+       int saved, ctr;
+
+       set_fs(0x0000);
+       set_gs(0xffff);
+
+       saved = ctr = rdfs32(A20_TEST_ADDR);
+
+       while (loops--) {
+               wrfs32(++ctr, A20_TEST_ADDR);
+               io_delay();     /* Serialize and make delay constant */
+               ok = rdgs32(A20_TEST_ADDR+0x10) ^ ctr;
+               if (ok)
+                       break;
+       }
+
+       wrfs32(saved, A20_TEST_ADDR);
+       return ok;
+}
+
+/* Quick test to see if A20 is already enabled */
+static int a20_test_short(void)
+{
+       return a20_test(A20_TEST_SHORT);
+}
+
+/* Longer test that actually waits for A20 to come on line; this
+   is useful when dealing with the KBC or other slow external circuitry. */
+static int a20_test_long(void)
+{
+       return a20_test(A20_TEST_LONG);
+}
+
+static void enable_a20_bios(void)
+{
+       asm volatile("pushfl; int $0x15; popfl"
+                    : : "a" ((u16)0x2401));
+}
+
+static void enable_a20_kbc(void)
+{
+       empty_8042();
+
+       outb(0xd1, 0x64);       /* Command write */
+       empty_8042();
+
+       outb(0xdf, 0x60);       /* A20 on */
+       empty_8042();
+}
+
+static void enable_a20_fast(void)
+{
+       u8 port_a;
+
+       port_a = inb(0x92);     /* Configuration port A */
+       port_a |=  0x02;        /* Enable A20 */
+       port_a &= ~0x01;        /* Do not reset machine */
+       outb(port_a, 0x92);
+}
+
+/*
+ * Actual routine to enable A20; return 0 on ok, -1 on failure
+ */
+
+#define A20_ENABLE_LOOPS 255   /* Number of times to try */
+
+int enable_a20(void)
+{
+       int loops = A20_ENABLE_LOOPS;
+
+#if defined(CONFIG_X86_ELAN)
+       /* Elan croaks if we try to touch the KBC */
+       enable_a20_fast();
+       while (!a20_test_long())
+               ;
+       return 0;
+#elif defined(CONFIG_X86_VOYAGER)
+       /* On Voyager, a20_test() is unsafe? */
+       enable_a20_kbc();
+       return 0;
+#else
+       while (loops--) {
+               /* First, check to see if A20 is already enabled
+                  (legacy free, etc.) */
+               if (a20_test_short())
+                       return 0;
+
+               /* Next, try the BIOS (INT 0x15, AX=0x2401) */
+               enable_a20_bios();
+               if (a20_test_short())
+                       return 0;
+
+               /* Try enabling A20 through the keyboard controller */
+               empty_8042();
+               if (a20_test_short())
+                       return 0; /* BIOS worked, but with delayed reaction */
+
+               enable_a20_kbc();
+               if (a20_test_long())
+                       return 0;
+
+               /* Finally, try enabling the "fast A20 gate" */
+               enable_a20_fast();
+               if (a20_test_long())
+                       return 0;
+       }
+
+       return -1;
+#endif
+}
diff --git a/arch/i386/boot/apm.c b/arch/i386/boot/apm.c
new file mode 100644 (file)
index 0000000..a34087c
--- /dev/null
@@ -0,0 +1,97 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   Original APM BIOS checking by Stephen Rothwell, May 1994
+ *   (sfr@canb.auug.org.au)
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/apm.c
+ *
+ * Get APM BIOS information
+ */
+
+#include "boot.h"
+
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+
+int query_apm_bios(void)
+{
+       u16 ax, bx, cx, dx, di;
+       u32 ebx, esi;
+       u8 err;
+
+       /* APM BIOS installation check */
+       ax = 0x5300;
+       bx = cx = 0;
+       asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
+                    : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
+                    : : "esi", "edi");
+
+       if (err)
+               return -1;              /* No APM BIOS */
+
+       if (bx != 0x504d)       /* "PM" signature */
+               return -1;
+
+       if (cx & 0x02)          /* 32 bits supported? */
+               return -1;
+
+       /* Disconnect first, just in case */
+       ax = 0x5304;
+       asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
+                    : "+a" (ax)
+                    : : "ebx", "ecx", "edx", "esi", "edi");
+
+       /* Paranoia */
+       ebx = esi = 0;
+       cx = dx = di = 0;
+
+       /* 32-bit connect */
+       asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6"
+                    : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx),
+                      "+S" (esi), "+D" (di), "=m" (err)
+                    : "a" (0x5303));
+
+       boot_params.apm_bios_info.cseg = ax;
+       boot_params.apm_bios_info.offset = ebx;
+       boot_params.apm_bios_info.cseg_16 = cx;
+       boot_params.apm_bios_info.dseg = dx;
+       boot_params.apm_bios_info.cseg_len = (u16)esi;
+       boot_params.apm_bios_info.cseg_16_len = esi >> 16;
+       boot_params.apm_bios_info.dseg_len = di;
+
+       if (err)
+               return -1;
+
+       /* Redo the installation check as the 32-bit connect;
+          some BIOSes return different flags this way... */
+
+       ax = 0x5300;
+       bx = cx = 0;
+       asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
+                    : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
+                    : : "esi", "edi");
+
+       if (err || bx != 0x504d) {
+               /* Failure with 32-bit connect, try to disconect and ignore */
+               ax = 0x5304;
+               bx = 0;
+               asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
+                            : "+a" (ax), "+b" (bx)
+                            : : "ecx", "edx", "esi", "edi");
+               return -1;
+       }
+
+       boot_params.apm_bios_info.version = ax;
+       boot_params.apm_bios_info.flags = cx;
+       return 0;
+}
+
+#endif
diff --git a/arch/i386/boot/bitops.h b/arch/i386/boot/bitops.h
new file mode 100644 (file)
index 0000000..8dcc8dc
--- /dev/null
@@ -0,0 +1,45 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/bitops.h
+ *
+ * Very simple bitops for the boot code.
+ */
+
+#ifndef BOOT_BITOPS_H
+#define BOOT_BITOPS_H
+#define _LINUX_BITOPS_H                /* Inhibit inclusion of <linux/bitops.h> */
+
+static inline int constant_test_bit(int nr, const void *addr)
+{
+       const u32 *p = (const u32 *)addr;
+       return ((1UL << (nr & 31)) & (p[nr >> 5])) != 0;
+}
+static inline int variable_test_bit(int nr, const void *addr)
+{
+       u8 v;
+       const u32 *p = (const u32 *)addr;
+
+       asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr));
+       return v;
+}
+
+#define test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ constant_test_bit((nr),(addr)) : \
+ variable_test_bit((nr),(addr)))
+
+static inline void set_bit(int nr, void *addr)
+{
+       asm("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr));
+}
+
+#endif /* BOOT_BITOPS_H */
diff --git a/arch/i386/boot/boot.h b/arch/i386/boot/boot.h
new file mode 100644 (file)
index 0000000..0329c4f
--- /dev/null
@@ -0,0 +1,296 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/boot.h
+ *
+ * Header file for the real-mode kernel code
+ */
+
+#ifndef BOOT_BOOT_H
+#define BOOT_BOOT_H
+
+#ifndef __ASSEMBLY__
+
+#include <stdarg.h>
+#include <linux/types.h>
+#include <linux/edd.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+/* Useful macros */
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+
+extern struct setup_header hdr;
+extern struct boot_params boot_params;
+
+/* Basic port I/O */
+static inline void outb(u8 v, u16 port)
+{
+       asm volatile("outb %0,%1" : : "a" (v), "dN" (port));
+}
+static inline u8 inb(u16 port)
+{
+       u8 v;
+       asm volatile("inb %1,%0" : "=a" (v) : "dN" (port));
+       return v;
+}
+
+static inline void outw(u16 v, u16 port)
+{
+       asm volatile("outw %0,%1" : : "a" (v), "dN" (port));
+}
+static inline u16 inw(u16 port)
+{
+       u16 v;
+       asm volatile("inw %1,%0" : "=a" (v) : "dN" (port));
+       return v;
+}
+
+static inline void outl(u32 v, u16 port)
+{
+       asm volatile("outl %0,%1" : : "a" (v), "dn" (port));
+}
+static inline u32 inl(u32 port)
+{
+       u32 v;
+       asm volatile("inl %1,%0" : "=a" (v) : "dN" (port));
+       return v;
+}
+
+static inline void io_delay(void)
+{
+       const u16 DELAY_PORT = 0x80;
+       asm volatile("outb %%al,%0" : : "dN" (DELAY_PORT));
+}
+
+/* These functions are used to reference data in other segments. */
+
+static inline u16 ds(void)
+{
+       u16 seg;
+       asm("movw %%ds,%0" : "=rm" (seg));
+       return seg;
+}
+
+static inline void set_fs(u16 seg)
+{
+       asm volatile("movw %0,%%fs" : : "rm" (seg));
+}
+static inline u16 fs(void)
+{
+       u16 seg;
+       asm("movw %%fs,%0" : "=rm" (seg));
+       return seg;
+}
+
+static inline void set_gs(u16 seg)
+{
+       asm volatile("movw %0,%%gs" : : "rm" (seg));
+}
+static inline u16 gs(void)
+{
+       u16 seg;
+       asm("movw %%gs,%0" : "=rm" (seg));
+       return seg;
+}
+
+typedef unsigned int addr_t;
+
+static inline u8 rdfs8(addr_t addr)
+{
+       u8 v;
+       asm("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
+       return v;
+}
+static inline u16 rdfs16(addr_t addr)
+{
+       u16 v;
+       asm("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
+       return v;
+}
+static inline u32 rdfs32(addr_t addr)
+{
+       u32 v;
+       asm("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
+       return v;
+}
+
+static inline void wrfs8(u8 v, addr_t addr)
+{
+       asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "r" (v));
+}
+static inline void wrfs16(u16 v, addr_t addr)
+{
+       asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "r" (v));
+}
+static inline void wrfs32(u32 v, addr_t addr)
+{
+       asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "r" (v));
+}
+
+static inline u8 rdgs8(addr_t addr)
+{
+       u8 v;
+       asm("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
+       return v;
+}
+static inline u16 rdgs16(addr_t addr)
+{
+       u16 v;
+       asm("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
+       return v;
+}
+static inline u32 rdgs32(addr_t addr)
+{
+       u32 v;
+       asm("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
+       return v;
+}
+
+static inline void wrgs8(u8 v, addr_t addr)
+{
+       asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "r" (v));
+}
+static inline void wrgs16(u16 v, addr_t addr)
+{
+       asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "r" (v));
+}
+static inline void wrgs32(u32 v, addr_t addr)
+{
+       asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "r" (v));
+}
+
+/* Note: these only return true/false, not a signed return value! */
+static inline int memcmp(const void *s1, const void *s2, size_t len)
+{
+       u8 diff;
+       asm("repe; cmpsb; setnz %0"
+           : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+       return diff;
+}
+
+static inline int memcmp_fs(const void *s1, addr_t s2, size_t len)
+{
+       u8 diff;
+       asm("fs; repe; cmpsb; setnz %0"
+           : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+       return diff;
+}
+static inline int memcmp_gs(const void *s1, addr_t s2, size_t len)
+{
+       u8 diff;
+       asm("gs; repe; cmpsb; setnz %0"
+           : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+       return diff;
+}
+
+static inline int isdigit(int ch)
+{
+       return (ch >= '0') && (ch <= '9');
+}
+
+/* Heap -- available for dynamic lists. */
+#define STACK_SIZE     512     /* Minimum number of bytes for stack */
+
+extern char _end[];
+extern char *HEAP;
+extern char *heap_end;
+#define RESET_HEAP() ((void *)( HEAP = _end ))
+static inline char *__get_heap(size_t s, size_t a, size_t n)
+{
+       char *tmp;
+
+       HEAP = (char *)(((size_t)HEAP+(a-1)) & ~(a-1));
+       tmp = HEAP;
+       HEAP += s*n;
+       return tmp;
+}
+#define GET_HEAP(type, n) \
+       ((type *)__get_heap(sizeof(type),__alignof__(type),(n)))
+
+static inline int heap_free(void)
+{
+       return heap_end-HEAP;
+}
+
+/* copy.S */
+
+void copy_to_fs(addr_t dst, void *src, size_t len);
+void *copy_from_fs(void *dst, addr_t src, size_t len);
+void copy_to_gs(addr_t dst, void *src, size_t len);
+void *copy_from_gs(void *dst, addr_t src, size_t len);
+void *memcpy(void *dst, void *src, size_t len);
+void *memset(void *dst, int c, size_t len);
+
+#define memcpy(d,s,l) __builtin_memcpy(d,s,l)
+#define memset(d,c,l) __builtin_memset(d,c,l)
+
+/* a20.c */
+int enable_a20(void);
+
+/* apm.c */
+int query_apm_bios(void);
+
+/* cmdline.c */
+int cmdline_find_option(const char *option, char *buffer, int bufsize);
+
+/* cpu.c, cpucheck.c */
+int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
+int validate_cpu(void);
+
+/* edd.c */
+void query_edd(void);
+
+/* header.S */
+void __attribute__((noreturn)) die(void);
+
+/* mca.c */
+int query_mca(void);
+
+/* memory.c */
+int detect_memory(void);
+
+/* pm.c */
+void __attribute__((noreturn)) go_to_protected_mode(void);
+
+/* pmjump.S */
+void __attribute__((noreturn))
+       protected_mode_jump(u32 entrypoint, u32 bootparams);
+
+/* printf.c */
+int sprintf(char *buf, const char *fmt, ...);
+int vsprintf(char *buf, const char *fmt, va_list args);
+int printf(const char *fmt, ...);
+
+/* string.c */
+int strcmp(const char *str1, const char *str2);
+size_t strnlen(const char *s, size_t maxlen);
+unsigned int atou(const char *s);
+
+/* tty.c */
+void puts(const char *);
+void putchar(int);
+int getchar(void);
+void kbd_flush(void);
+int getchar_timeout(void);
+
+/* video.c */
+void set_video(void);
+
+/* video-vesa.c */
+void vesa_store_edid(void);
+
+/* voyager.c */
+int query_voyager(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* BOOT_BOOT_H */
diff --git a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
deleted file mode 100644 (file)
index 011b7a4..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *     bootsect.S              Copyright (C) 1991, 1992 Linus Torvalds
- *
- *     modified by Drew Eckhardt
- *     modified by Bruce Evans (bde)
- *     modified by Chris Noe (May 1999) (as86 -> gas)
- *     gutted by H. Peter Anvin (Jan 2003)
- *
- * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
- * addresses must be multiplied by 16 to obtain their respective linear
- * addresses. To avoid confusion, linear addresses are written using leading
- * hex while segment addresses are written as segment:offset.
- *
- */
-
-#include <asm/boot.h>
-
-SETUPSECTS     = 4                     /* default nr of setup-sectors */
-BOOTSEG                = 0x07C0                /* original address of boot-sector */
-INITSEG                = DEF_INITSEG           /* we move boot here - out of the way */
-SETUPSEG       = DEF_SETUPSEG          /* setup starts here */
-SYSSEG         = DEF_SYSSEG            /* system loaded at 0x10000 (65536) */
-SYSSIZE                = DEF_SYSSIZE           /* system size: # of 16-byte clicks */
-                                       /* to be loaded */
-ROOT_DEV       = 0                     /* ROOT_DEV is now written by "build" */
-SWAP_DEV       = 0                     /* SWAP_DEV is now written by "build" */
-
-#ifndef SVGA_MODE
-#define SVGA_MODE ASK_VGA
-#endif
-
-#ifndef RAMDISK
-#define RAMDISK 0
-#endif
-
-#ifndef ROOT_RDONLY
-#define ROOT_RDONLY 1
-#endif
-
-.code16
-.text
-
-.global _start
-_start:
-
-       # Normalize the start address
-       jmpl    $BOOTSEG, $start2
-
-start2:
-       movw    %cs, %ax
-       movw    %ax, %ds
-       movw    %ax, %es
-       movw    %ax, %ss
-       movw    $0x7c00, %sp
-       sti
-       cld
-
-       movw    $bugger_off_msg, %si
-
-msg_loop:
-       lodsb
-       andb    %al, %al
-       jz      die
-       movb    $0xe, %ah
-       movw    $7, %bx
-       int     $0x10
-       jmp     msg_loop
-
-die:
-       # Allow the user to press a key, then reboot
-       xorw    %ax, %ax
-       int     $0x16
-       int     $0x19
-
-       # int 0x19 should never return.  In case it does anyway,
-       # invoke the BIOS reset code...
-       ljmp    $0xf000,$0xfff0
-
-
-bugger_off_msg:
-       .ascii  "Direct booting from floppy is no longer supported.\r\n"
-       .ascii  "Please use a boot loader program instead.\r\n"
-       .ascii  "\n"
-       .ascii  "Remove disk and press any key to reboot . . .\r\n"
-       .byte   0
-
-
-       # Kernel attributes; used by setup
-
-       .org 497
-setup_sects:   .byte SETUPSECTS
-root_flags:    .word ROOT_RDONLY
-syssize:       .word SYSSIZE
-swap_dev:      .word SWAP_DEV
-ram_size:      .word RAMDISK
-vid_mode:      .word SVGA_MODE
-root_dev:      .word ROOT_DEV
-boot_flag:     .word 0xAA55
diff --git a/arch/i386/boot/cmdline.c b/arch/i386/boot/cmdline.c
new file mode 100644 (file)
index 0000000..34bb778
--- /dev/null
@@ -0,0 +1,97 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/cmdline.c
+ *
+ * Simple command-line parser for early boot.
+ */
+
+#include "boot.h"
+
+static inline int myisspace(u8 c)
+{
+       return c <= ' ';        /* Close enough approximation */
+}
+
+/*
+ * Find a non-boolean option, that is, "option=argument".  In accordance
+ * with standard Linux practice, if this option is repeated, this returns
+ * the last instance on the command line.
+ *
+ * Returns the length of the argument (regardless of if it was
+ * truncated to fit in the buffer), or -1 on not found.
+ */
+int cmdline_find_option(const char *option, char *buffer, int bufsize)
+{
+       u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
+       addr_t cptr;
+       char c;
+       int len = -1;
+       const char *opptr = NULL;
+       char *bufptr = buffer;
+       enum {
+               st_wordstart,   /* Start of word/after whitespace */
+               st_wordcmp,     /* Comparing this word */
+               st_wordskip,    /* Miscompare, skip */
+               st_bufcpy       /* Copying this to buffer */
+       } state = st_wordstart;
+
+       if (!cmdline_ptr || cmdline_ptr >= 0x100000)
+               return -1;      /* No command line, or inaccessible */
+
+       cptr = cmdline_ptr & 0xf;
+       set_fs(cmdline_ptr >> 4);
+
+       while (cptr < 0x10000 && (c = rdfs8(cptr++))) {
+               switch (state) {
+               case st_wordstart:
+                       if (myisspace(c))
+                               break;
+
+                       /* else */
+                       state = st_wordcmp;
+                       opptr = option;
+                       /* fall through */
+
+               case st_wordcmp:
+                       if (c == '=' && !*opptr) {
+                               len = 0;
+                               bufptr = buffer;
+                               state = st_bufcpy;
+                       } else if (myisspace(c)) {
+                               state = st_wordstart;
+                       } else if (c != *opptr++) {
+                               state = st_wordskip;
+                       }
+                       break;
+
+               case st_wordskip:
+                       if (myisspace(c))
+                               state = st_wordstart;
+                       break;
+
+               case st_bufcpy:
+                       if (myisspace(c)) {
+                               state = st_wordstart;
+                       } else {
+                               if (len < bufsize-1)
+                                       *bufptr++ = c;
+                               len++;
+                       }
+                       break;
+               }
+       }
+
+       if (bufsize)
+               *bufptr = '\0';
+
+       return len;
+}
diff --git a/arch/i386/boot/code16gcc.h b/arch/i386/boot/code16gcc.h
new file mode 100644 (file)
index 0000000..3bd8480
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * code16gcc.h
+ *
+ * This file is -include'd when compiling 16-bit C code.
+ * Note: this asm() needs to be emitted before gcc omits any code.
+ * Depending on gcc version, this requires -fno-unit-at-a-time or
+ * -fno-toplevel-reorder.
+ *
+ * Hopefully gcc will eventually have a real -m16 option so we can
+ * drop this hack long term.
+ */
+
+#ifndef __ASSEMBLY__
+asm(".code16gcc");
+#endif
index a661217f33ec4eeba811cb9d987f626f5f7c3838..189fa1dbefcc27ece79bac59fc2d11b83d09e38f 100644 (file)
@@ -9,9 +9,14 @@ targets                := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \
 EXTRA_AFLAGS   := -traditional
 
 LDFLAGS_vmlinux := -T
-CFLAGS_misc.o += -fPIC
 hostprogs-y    := relocs
 
+CFLAGS  := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
+          -fno-strict-aliasing -fPIC \
+          $(call cc-option,-ffreestanding) \
+          $(call cc-option,-fno-stack-protector)
+LDFLAGS := -m elf_i386
+
 $(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
        $(call if_changed,ld)
        @:
index 3517a32aaf4152a67098f70dc43e1f43f16d5851..f35ea2237522c0267139af7666e2875b571dd4b4 100644 (file)
@@ -45,10 +45,10 @@ startup_32:
  * at and where we were actually loaded at.  This can only be done
  * with a short local call on x86.  Nothing  else will tell us what
  * address we are running at.  The reserved chunk of the real-mode
- * data at 0x34-0x3f are used as the stack for this calculation.
- * Only 4 bytes are needed.
+ * data at 0x1e4 (defined as a scratch field) are used as the stack
+ * for this calculation. Only 4 bytes are needed.
  */
-       leal 0x40(%esi), %esp
+       leal (0x1e4+4)(%esi), %esp
        call 1f
 1:     popl %ebp
        subl $1b, %ebp
diff --git a/arch/i386/boot/copy.S b/arch/i386/boot/copy.S
new file mode 100644 (file)
index 0000000..ef127e5
--- /dev/null
@@ -0,0 +1,101 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/copy.S
+ *
+ * Memory copy routines
+ */
+
+       .code16gcc
+       .text
+
+       .globl  memcpy
+       .type   memcpy, @function
+memcpy:
+       pushw   %si
+       pushw   %di
+       movw    %ax, %di
+       movw    %dx, %si
+       pushw   %cx
+       shrw    $2, %cx
+       rep; movsl
+       popw    %cx
+       andw    $3, %cx
+       rep; movsb
+       popw    %di
+       popw    %si
+       ret
+       .size   memcpy, .-memcpy
+
+       .globl  memset
+       .type   memset, @function
+memset:
+       pushw   %di
+       movw    %ax, %di
+       movzbl  %dl, %eax
+       imull   $0x01010101,%eax
+       pushw   %cx
+       shrw    $2, %cx
+       rep; stosl
+       popw    %cx
+       andw    $3, %cx
+       rep; stosb
+       popw    %di
+       ret
+       .size   memset, .-memset
+
+       .globl  copy_from_fs
+       .type   copy_from_fs, @function
+copy_from_fs:
+       pushw   %ds
+       pushw   %fs
+       popw    %ds
+       call    memcpy
+       popw    %ds
+       ret
+       .size   copy_from_fs, .-copy_from_fs
+
+       .globl  copy_to_fs
+       .type   copy_to_fs, @function
+copy_to_fs:
+       pushw   %es
+       pushw   %fs
+       popw    %es
+       call    memcpy
+       popw    %es
+       ret
+       .size   copy_to_fs, .-copy_to_fs
+
+#if 0 /* Not currently used, but can be enabled as needed */
+
+       .globl  copy_from_gs
+       .type   copy_from_gs, @function
+copy_from_gs:
+       pushw   %ds
+       pushw   %gs
+       popw    %ds
+       call    memcpy
+       popw    %ds
+       ret
+       .size   copy_from_gs, .-copy_from_gs
+       .globl  copy_to_gs
+
+       .type   copy_to_gs, @function
+copy_to_gs:
+       pushw   %es
+       pushw   %gs
+       popw    %es
+       call    memcpy
+       popw    %es
+       ret
+       .size   copy_to_gs, .-copy_to_gs
+
+#endif
diff --git a/arch/i386/boot/cpu.c b/arch/i386/boot/cpu.c
new file mode 100644 (file)
index 0000000..2a5c32d
--- /dev/null
@@ -0,0 +1,69 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/cpu.c
+ *
+ * Check for obligatory CPU features and abort if the features are not
+ * present.
+ */
+
+#include "boot.h"
+#include "bitops.h"
+#include <asm/cpufeature.h>
+
+static char *cpu_name(int level)
+{
+       static char buf[6];
+
+       if (level == 64) {
+               return "x86-64";
+       } else {
+               sprintf(buf, "i%d86", level);
+               return buf;
+       }
+}
+
+int validate_cpu(void)
+{
+       u32 *err_flags;
+       int cpu_level, req_level;
+
+       check_cpu(&cpu_level, &req_level, &err_flags);
+
+       if (cpu_level < req_level) {
+               printf("This kernel requires an %s CPU, ",
+                      cpu_name(req_level));
+               printf("but only detected an %s CPU.\n",
+                      cpu_name(cpu_level));
+               return -1;
+       }
+
+       if (err_flags) {
+               int i, j;
+               puts("This kernel requires the following features "
+                    "not present on the CPU:\n");
+
+               for (i = 0; i < NCAPINTS; i++) {
+                       u32 e = err_flags[i];
+
+                       for (j = 0; j < 32; j++) {
+                               if (e & 1)
+                                       printf("%d:%d ", i, j);
+
+                               e >>= 1;
+                       }
+               }
+               putchar('\n');
+               return -1;
+       } else {
+               return 0;
+       }
+}
diff --git a/arch/i386/boot/cpucheck.c b/arch/i386/boot/cpucheck.c
new file mode 100644 (file)
index 0000000..8b0f447
--- /dev/null
@@ -0,0 +1,267 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/cpucheck.c
+ *
+ * Check for obligatory CPU features and abort if the features are not
+ * present.  This code should be compilable as 16-, 32- or 64-bit
+ * code, so be very careful with types and inline assembly.
+ *
+ * This code should not contain any messages; that requires an
+ * additional wrapper.
+ *
+ * As written, this code is not safe for inclusion into the kernel
+ * proper (after FPU initialization, in particular).
+ */
+
+#ifdef _SETUP
+# include "boot.h"
+# include "bitops.h"
+#endif
+#include <linux/types.h>
+#include <asm/cpufeature.h>
+#include <asm/processor-flags.h>
+#include <asm/required-features.h>
+#include <asm/msr-index.h>
+
+struct cpu_features {
+       int level;              /* Family, or 64 for x86-64 */
+       int model;
+       u32 flags[NCAPINTS];
+};
+
+static struct cpu_features cpu;
+static u32 cpu_vendor[3];
+static u32 err_flags[NCAPINTS];
+
+#ifdef CONFIG_X86_64
+static const int req_level = 64;
+#elif defined(CONFIG_X86_MINIMUM_CPU_FAMILY)
+static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY;
+#else
+static const int req_level = 3;
+#endif
+
+static const u32 req_flags[NCAPINTS] =
+{
+       REQUIRED_MASK0,
+       REQUIRED_MASK1,
+       REQUIRED_MASK2,
+       REQUIRED_MASK3,
+       REQUIRED_MASK4,
+       REQUIRED_MASK5,
+       REQUIRED_MASK6,
+       REQUIRED_MASK7,
+};
+
+#define A32(a,b,c,d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
+
+static int is_amd(void)
+{
+       return cpu_vendor[0] == A32('A','u','t','h') &&
+              cpu_vendor[1] == A32('e','n','t','i') &&
+              cpu_vendor[2] == A32('c','A','M','D');
+}
+
+static int is_centaur(void)
+{
+       return cpu_vendor[0] == A32('C','e','n','t') &&
+              cpu_vendor[1] == A32('a','u','r','H') &&
+              cpu_vendor[2] == A32('a','u','l','s');
+}
+
+static int is_transmeta(void)
+{
+       return cpu_vendor[0] == A32('G','e','n','u') &&
+              cpu_vendor[1] == A32('i','n','e','T') &&
+              cpu_vendor[2] == A32('M','x','8','6');
+}
+
+static int has_fpu(void)
+{
+       u16 fcw = -1, fsw = -1;
+       u32 cr0;
+
+       asm("movl %%cr0,%0" : "=r" (cr0));
+       if (cr0 & (X86_CR0_EM|X86_CR0_TS)) {
+               cr0 &= ~(X86_CR0_EM|X86_CR0_TS);
+               asm volatile("movl %0,%%cr0" : : "r" (cr0));
+       }
+
+       asm("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw));
+
+       return fsw == 0 && (fcw & 0x103f) == 0x003f;
+}
+
+static int has_eflag(u32 mask)
+{
+       u32 f0, f1;
+
+       asm("pushfl ; "
+           "pushfl ; "
+           "popl %0 ; "
+           "movl %0,%1 ; "
+           "xorl %2,%1 ; "
+           "pushl %1 ; "
+           "popfl ; "
+           "pushfl ; "
+           "popl %1 ; "
+           "popfl"
+           : "=r" (f0), "=r" (f1)
+           : "g" (mask));
+
+       return !!((f0^f1) & mask);
+}
+
+static void get_flags(void)
+{
+       u32 max_intel_level, max_amd_level;
+       u32 tfms;
+
+       if (has_fpu())
+               set_bit(X86_FEATURE_FPU, cpu.flags);
+
+       if (has_eflag(X86_EFLAGS_ID)) {
+               asm("cpuid"
+                   : "=a" (max_intel_level),
+                     "=b" (cpu_vendor[0]),
+                     "=d" (cpu_vendor[1]),
+                     "=c" (cpu_vendor[2])
+                   : "a" (0));
+
+               if (max_intel_level >= 0x00000001 &&
+                   max_intel_level <= 0x0000ffff) {
+                       asm("cpuid"
+                           : "=a" (tfms),
+                             "=c" (cpu.flags[4]),
+                             "=d" (cpu.flags[0])
+                           : "a" (0x00000001)
+                           : "ebx");
+                       cpu.level = (tfms >> 8) & 15;
+                       cpu.model = (tfms >> 4) & 15;
+                       if (cpu.level >= 6)
+                               cpu.model += ((tfms >> 16) & 0xf) << 4;
+               }
+
+               asm("cpuid"
+                   : "=a" (max_amd_level)
+                   : "a" (0x80000000)
+                   : "ebx", "ecx", "edx");
+
+               if (max_amd_level >= 0x80000001 &&
+                   max_amd_level <= 0x8000ffff) {
+                       u32 eax = 0x80000001;
+                       asm("cpuid"
+                           : "+a" (eax),
+                             "=c" (cpu.flags[6]),
+                             "=d" (cpu.flags[1])
+                           : : "ebx");
+               }
+       }
+}
+
+/* Returns a bitmask of which words we have error bits in */
+static int check_flags(void)
+{
+       u32 err;
+       int i;
+
+       err = 0;
+       for (i = 0; i < NCAPINTS; i++) {
+               err_flags[i] = req_flags[i] & ~cpu.flags[i];
+               if (err_flags[i])
+                       err |= 1 << i;
+       }
+
+       return err;
+}
+
+/*
+ * Returns -1 on error.
+ *
+ * *cpu_level is set to the current CPU level; *req_level to the required
+ * level.  x86-64 is considered level 64 for this purpose.
+ *
+ * *err_flags_ptr is set to the flags error array if there are flags missing.
+ */
+int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
+{
+       int err;
+
+       memset(&cpu.flags, 0, sizeof cpu.flags);
+       cpu.level = 3;
+
+       if (has_eflag(X86_EFLAGS_AC))
+               cpu.level = 4;
+
+       get_flags();
+       err = check_flags();
+
+       if (test_bit(X86_FEATURE_LM, cpu.flags))
+               cpu.level = 64;
+
+       if (err == 0x01 &&
+           !(err_flags[0] &
+             ~((1 << X86_FEATURE_XMM)|(1 << X86_FEATURE_XMM2))) &&
+           is_amd()) {
+               /* If this is an AMD and we're only missing SSE+SSE2, try to
+                  turn them on */
+
+               u32 ecx = MSR_K7_HWCR;
+               u32 eax, edx;
+
+               asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+               eax &= ~(1 << 15);
+               asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+               get_flags();    /* Make sure it really did something */
+               err = check_flags();
+       } else if (err == 0x01 &&
+                  !(err_flags[0] & ~(1 << X86_FEATURE_CX8)) &&
+                  is_centaur() && cpu.model >= 6) {
+               /* If this is a VIA C3, we might have to enable CX8
+                  explicitly */
+
+               u32 ecx = MSR_VIA_FCR;
+               u32 eax, edx;
+
+               asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+               eax |= (1<<1)|(1<<7);
+               asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+               set_bit(X86_FEATURE_CX8, cpu.flags);
+               err = check_flags();
+       } else if (err == 0x01 && is_transmeta()) {
+               /* Transmeta might have masked feature bits in word 0 */
+
+               u32 ecx = 0x80860004;
+               u32 eax, edx;
+               u32 level = 1;
+
+               asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+               asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx));
+               asm("cpuid"
+                   : "+a" (level), "=d" (cpu.flags[0])
+                   : : "ecx", "ebx");
+               asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+               err = check_flags();
+       }
+
+       if (err_flags_ptr)
+               *err_flags_ptr = err ? err_flags : NULL;
+       if (cpu_level_ptr)
+               *cpu_level_ptr = cpu.level;
+       if (req_level_ptr)
+               *req_level_ptr = req_level;
+
+       return (cpu.level < req_level || err) ? -1 : 0;
+}
diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S
deleted file mode 100644 (file)
index 3432136..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * BIOS Enhanced Disk Drive support
- * Copyright (C) 2002, 2003, 2004 Dell, Inc.
- * by Matt Domsch <Matt_Domsch@dell.com> October 2002
- * conformant to T13 Committee www.t13.org
- *   projects 1572D, 1484D, 1386D, 1226DT
- * disk signature read by Matt Domsch <Matt_Domsch@dell.com>
- *     and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004
- * legacy CHS retrieval by Patrick J. LoPresti <patl@users.sourceforge.net>
- *      March 2004
- * Command line option parsing, Matt Domsch, November 2004
- */
-
-#include <linux/edd.h>
-#include <asm/setup.h>
-
-#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
-
-# It is assumed that %ds == INITSEG here
-
-       movb    $0, (EDD_MBR_SIG_NR_BUF)
-       movb    $0, (EDDNR)
-
-# Check the command line for options:
-# edd=of  disables EDD completely  (edd=off)
-# edd=sk  skips the MBR test    (edd=skipmbr)
-# edd=on  re-enables EDD (edd=on)
-
-       pushl   %esi
-       movw    $edd_mbr_sig_start, %di # Default to edd=on
-
-       movl    %cs:(cmd_line_ptr), %esi
-       andl    %esi, %esi
-       jz      old_cl                  # Old boot protocol?
-
-# Convert to a real-mode pointer in fs:si
-       movl    %esi, %eax
-       shrl    $4, %eax
-       movw    %ax, %fs
-       andw    $0xf, %si
-       jmp     have_cl_pointer
-
-# Old-style boot protocol?
-old_cl:
-       push    %ds                     # aka INITSEG
-       pop     %fs
-
-       cmpw    $0xa33f, (0x20)
-       jne     done_cl                 # No command line at all?
-       movw    (0x22), %si             # Pointer relative to INITSEG
-
-# fs:si has the pointer to the command line now
-have_cl_pointer:
-
-# Loop through kernel command line one byte at a time.  Just in
-# case the loader is buggy and failed to null-terminate the command line
-# terminate if we get close enough to the end of the segment that we
-# cannot fit "edd=XX"...
-cl_atspace:
-       cmpw    $-5, %si                # Watch for segment wraparound
-       jae     done_cl
-       movl    %fs:(%si), %eax
-       andb    %al, %al                # End of line?
-       jz      done_cl
-       cmpl    $EDD_CL_EQUALS, %eax
-       jz      found_edd_equals
-       cmpb    $0x20, %al              # <= space consider whitespace
-       ja      cl_skipword
-       incw    %si
-       jmp     cl_atspace
-
-cl_skipword:
-       cmpw    $-5, %si                # Watch for segment wraparound
-       jae     done_cl
-       movb    %fs:(%si), %al          # End of string?
-       andb    %al, %al
-       jz      done_cl
-       cmpb    $0x20, %al
-       jbe     cl_atspace
-       incw    %si
-       jmp     cl_skipword
-
-found_edd_equals:
-# only looking at first two characters after equals
-# late overrides early on the command line, so keep going after finding something
-       movw    %fs:4(%si), %ax
-       cmpw    $EDD_CL_OFF, %ax        # edd=of
-       je      do_edd_off
-       cmpw    $EDD_CL_SKIP, %ax       # edd=sk
-       je      do_edd_skipmbr
-       cmpw    $EDD_CL_ON, %ax         # edd=on
-       je      do_edd_on
-       jmp     cl_skipword
-do_edd_skipmbr:
-       movw    $edd_start, %di
-       jmp     cl_skipword
-do_edd_off:
-       movw    $edd_done, %di
-       jmp     cl_skipword
-do_edd_on:
-       movw    $edd_mbr_sig_start, %di
-       jmp     cl_skipword
-
-done_cl:
-       popl    %esi
-       jmpw    *%di
-
-# Read the first sector of each BIOS disk device and store the 4-byte signature
-edd_mbr_sig_start:
-       movb    $0x80, %dl                      # from device 80
-       movw    $EDD_MBR_SIG_BUF, %bx           # store buffer ptr in bx
-edd_mbr_sig_read:
-       movl    $0xFFFFFFFF, %eax
-       movl    %eax, (%bx)                     # assume failure
-       pushw   %bx
-       movb    $READ_SECTORS, %ah
-       movb    $1, %al                         # read 1 sector
-       movb    $0, %dh                         # at head 0
-       movw    $1, %cx                         # cylinder 0, sector 0
-       pushw   %es
-       pushw   %ds
-       popw    %es
-       movw    $EDDBUF, %bx                    # disk's data goes into EDDBUF
-       pushw   %dx             # work around buggy BIOSes
-       stc                     # work around buggy BIOSes
-       int     $0x13
-       sti                     # work around buggy BIOSes
-       popw    %dx
-       popw    %es
-       popw    %bx
-       jc      edd_mbr_sig_done                # on failure, we're done.
-       cmpb    $0, %ah         # some BIOSes do not set CF
-       jne     edd_mbr_sig_done                # on failure, we're done.
-       movl    (EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR
-       movl    %eax, (%bx)                     # store success
-       incb    (EDD_MBR_SIG_NR_BUF)            # note that we stored something
-       incb    %dl                             # increment to next device
-       addw    $4, %bx                         # increment sig buffer ptr
-       cmpb    $EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF)  # Out of space?
-       jb      edd_mbr_sig_read                # keep looping
-edd_mbr_sig_done:
-
-# Do the BIOS Enhanced Disk Drive calls
-# This consists of two calls:
-#    int 13h ah=41h "Check Extensions Present"
-#    int 13h ah=48h "Get Device Parameters"
-#    int 13h ah=08h "Legacy Get Device Parameters"
-#
-# A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE) is reserved for our use
-# in the boot_params at EDDBUF.  The first four bytes of which are
-# used to store the device number, interface support map and version
-# results from fn41.  The next four bytes are used to store the legacy
-# cylinders, heads, and sectors from fn08. The following 74 bytes are used to
-# store the results from fn48.  Starting from device 80h, fn41, then fn48
-# are called and their results stored in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE).
-# Then the pointer is incremented to store the data for the next call.
-# This repeats until either a device doesn't exist, or until EDDMAXNR
-# devices have been stored.
-# The one tricky part is that ds:si always points EDDEXTSIZE bytes into
-# the structure, and the fn41 and fn08 results are stored at offsets
-# from there.  This removes the need to increment the pointer for
-# every store, and leaves it ready for the fn48 call.
-# A second one-byte buffer, EDDNR, in the boot_params stores
-# the number of BIOS devices which exist, up to EDDMAXNR.
-# In setup.c, copy_edd() stores both boot_params buffers away
-# for later use, as they would get overwritten otherwise.
-# This code is sensitive to the size of the structs in edd.h
-edd_start:
-                                               # %ds points to the bootsector
-                                                       # result buffer for fn48
-       movw    $EDDBUF+EDDEXTSIZE, %si         # in ds:si, fn41 results
-                                               # kept just before that
-       movb    $0x80, %dl                      # BIOS device 0x80
-
-edd_check_ext:
-       movb    $CHECKEXTENSIONSPRESENT, %ah    # Function 41
-       movw    $EDDMAGIC1, %bx                 # magic
-       int     $0x13                           # make the call
-       jc      edd_done                        # no more BIOS devices
-
-       cmpw    $EDDMAGIC2, %bx                 # is magic right?
-       jne     edd_next                        # nope, next...
-
-       movb    %dl, %ds:-8(%si)                # store device number
-       movb    %ah, %ds:-7(%si)                # store version
-       movw    %cx, %ds:-6(%si)                # store extensions
-       incb    (EDDNR)                         # note that we stored something
-
-edd_get_device_params:
-       movw    $EDDPARMSIZE, %ds:(%si)         # put size
-       movw    $0x0, %ds:2(%si)                # work around buggy BIOSes
-       movb    $GETDEVICEPARAMETERS, %ah       # Function 48
-       int     $0x13                           # make the call
-                                               # Don't check for fail return
-                                               # it doesn't matter.
-edd_get_legacy_chs:
-       xorw    %ax, %ax
-       movw    %ax, %ds:-4(%si)
-       movw    %ax, %ds:-2(%si)
-        # Ralf Brown's Interrupt List says to set ES:DI to
-       # 0000h:0000h "to guard against BIOS bugs"
-       pushw   %es
-       movw    %ax, %es
-       movw    %ax, %di
-       pushw   %dx                             # legacy call clobbers %dl
-       movb    $LEGACYGETDEVICEPARAMETERS, %ah # Function 08
-       int     $0x13                           # make the call
-       jc      edd_legacy_done                 # failed
-       movb    %cl, %al                        # Low 6 bits are max
-       andb    $0x3F, %al                      #   sector number
-       movb    %al, %ds:-1(%si)                # Record max sect
-       movb    %dh, %ds:-2(%si)                # Record max head number
-       movb    %ch, %al                        # Low 8 bits of max cyl
-       shr     $6, %cl
-       movb    %cl, %ah                        # High 2 bits of max cyl
-       movw    %ax, %ds:-4(%si)
-
-edd_legacy_done:
-       popw    %dx
-       popw    %es
-       movw    %si, %ax                        # increment si
-       addw    $EDDPARMSIZE+EDDEXTSIZE, %ax
-       movw    %ax, %si
-
-edd_next:
-       incb    %dl                             # increment to next device
-       cmpb    $EDDMAXNR, (EDDNR)              # Out of space?
-       jb      edd_check_ext                   # keep looping
-
-edd_done:
-#endif
diff --git a/arch/i386/boot/edd.c b/arch/i386/boot/edd.c
new file mode 100644 (file)
index 0000000..25a2824
--- /dev/null
@@ -0,0 +1,196 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/edd.c
+ *
+ * Get EDD BIOS disk information
+ */
+
+#include "boot.h"
+#include <linux/edd.h>
+
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+
+struct edd_dapa {
+       u8      pkt_size;
+       u8      rsvd;
+       u16     sector_cnt;
+       u16     buf_off, buf_seg;
+       u64     lba;
+       u64     buf_lin_addr;
+};
+
+/*
+ * Read the MBR (first sector) from a specific device.
+ */
+static int read_mbr(u8 devno, void *buf)
+{
+       struct edd_dapa dapa;
+       u16 ax, bx, cx, dx, si;
+
+       memset(&dapa, 0, sizeof dapa);
+       dapa.pkt_size = sizeof(dapa);
+       dapa.sector_cnt = 1;
+       dapa.buf_off = (size_t)buf;
+       dapa.buf_seg = ds();
+       /* dapa.lba = 0; */
+
+       ax = 0x4200;            /* Extended Read */
+       si = (size_t)&dapa;
+       dx = devno;
+       asm("pushfl; stc; int $0x13; setc %%al; popfl"
+           : "+a" (ax), "+S" (si), "+d" (dx)
+           : "m" (dapa)
+           : "ebx", "ecx", "edi", "memory");
+
+       if (!(u8)ax)
+               return 0;       /* OK */
+
+       ax = 0x0201;            /* Legacy Read, one sector */
+       cx = 0x0001;            /* Sector 0-0-1 */
+       dx = devno;
+       bx = (size_t)buf;
+       asm("pushfl; stc; int $0x13; setc %%al; popfl"
+           : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx)
+           : : "esi", "edi", "memory");
+
+       return -(u8)ax;         /* 0 or -1 */
+}
+
+static u32 read_mbr_sig(u8 devno, struct edd_info *ei)
+{
+       int sector_size;
+       char *mbrbuf_ptr, *mbrbuf_end;
+       u32 mbrsig;
+       u32 buf_base, mbr_base;
+       extern char _end[];
+       static char mbr_buf[1024];
+
+       sector_size = ei->params.bytes_per_sector;
+       if (!sector_size)
+               sector_size = 512; /* Best available guess */
+
+       buf_base = (ds() << 4) + (u32)&_end;
+       mbr_base = (buf_base+sector_size-1) & ~(sector_size-1);
+       mbrbuf_ptr = mbr_buf + (mbr_base-buf_base);
+       mbrbuf_end = mbrbuf_ptr + sector_size;
+
+       if (!(boot_params.hdr.loadflags & CAN_USE_HEAP))
+               return 0;
+       if (mbrbuf_end > (char *)(size_t)boot_params.hdr.heap_end_ptr)
+               return 0;
+
+       if (read_mbr(devno, mbrbuf_ptr))
+               return 0;
+
+       mbrsig = *(u32 *)&mbrbuf_ptr[EDD_MBR_SIG_OFFSET];
+       return mbrsig;
+}
+
+static int get_edd_info(u8 devno, struct edd_info *ei)
+{
+       u16 ax, bx, cx, dx, di;
+
+       memset(ei, 0, sizeof *ei);
+
+       /* Check Extensions Present */
+
+       ax = 0x4100;
+       bx = EDDMAGIC1;
+       dx = devno;
+       asm("pushfl; stc; int $0x13; setc %%al; popfl"
+           : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx)
+           : : "esi", "edi");
+
+       if ((u8)ax)
+               return -1;      /* No extended information */
+
+       if (bx != EDDMAGIC2)
+               return -1;
+
+       ei->device  = devno;
+       ei->version = ax >> 8;  /* EDD version number */
+       ei->interface_support = cx; /* EDD functionality subsets */
+
+       /* Extended Get Device Parameters */
+
+       ei->params.length = sizeof(ei->params);
+       ax = 0x4800;
+       dx = devno;
+       asm("pushfl; int $0x13; popfl"
+           : "+a" (ax), "+d" (dx)
+           : "S" (&ei->params)
+           : "ebx", "ecx", "edi");
+
+       /* Get legacy CHS parameters */
+
+       /* Ralf Brown recommends setting ES:DI to 0:0 */
+       ax = 0x0800;
+       dx = devno;
+       di = 0;
+       asm("pushw %%es; "
+           "movw %%di,%%es; "
+           "pushfl; stc; int $0x13; setc %%al; popfl; "
+           "popw %%es"
+           : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di)
+           : : "esi");
+
+       if ((u8)ax == 0) {
+               ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2);
+               ei->legacy_max_head = dx >> 8;
+               ei->legacy_sectors_per_track = cx & 0x3f;
+       }
+
+       return 0;
+}
+
+void query_edd(void)
+{
+       char eddarg[8];
+       int do_mbr = 1;
+       int do_edd = 1;
+       int devno;
+       struct edd_info ei, *edp;
+
+       if (cmdline_find_option("edd", eddarg, sizeof eddarg) > 0) {
+               if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip"))
+                       do_mbr = 0;
+               else if (!strcmp(eddarg, "off"))
+                       do_edd = 0;
+       }
+
+       edp = (struct edd_info *)boot_params.eddbuf;
+
+       if (!do_edd)
+               return;
+
+       for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) {
+               /*
+                * Scan the BIOS-supported hard disks and query EDD
+                * information...
+                */
+               get_edd_info(devno, &ei);
+
+               if (boot_params.eddbuf_entries < EDDMAXNR) {
+                       memcpy(edp, &ei, sizeof ei);
+                       edp++;
+                       boot_params.eddbuf_entries++;
+               }
+
+               if (do_mbr) {
+                       u32 mbr_sig;
+                       mbr_sig = read_mbr_sig(devno, &ei);
+                       boot_params.edd_mbr_sig_buffer[devno-0x80] = mbr_sig;
+               }
+       }
+}
+
+#endif
diff --git a/arch/i386/boot/header.S b/arch/i386/boot/header.S
new file mode 100644 (file)
index 0000000..6b9923f
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ *     header.S
+ *
+ *     Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ *     Based on bootsect.S and setup.S
+ *     modified by more people than can be counted
+ *
+ *     Rewritten as a common file by H. Peter Anvin (Apr 2007)
+ *
+ * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
+ * addresses must be multiplied by 16 to obtain their respective linear
+ * addresses. To avoid confusion, linear addresses are written using leading
+ * hex while segment addresses are written as segment:offset.
+ *
+ */
+
+#include <asm/segment.h>
+#include <linux/utsrelease.h>
+#include <asm/boot.h>
+#include <asm/e820.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include "boot.h"
+
+SETUPSECTS     = 4                     /* default nr of setup-sectors */
+BOOTSEG                = 0x07C0                /* original address of boot-sector */
+SYSSEG         = DEF_SYSSEG            /* system loaded at 0x10000 (65536) */
+SYSSIZE                = DEF_SYSSIZE           /* system size: # of 16-byte clicks */
+                                       /* to be loaded */
+ROOT_DEV       = 0                     /* ROOT_DEV is now written by "build" */
+SWAP_DEV       = 0                     /* SWAP_DEV is now written by "build" */
+
+#ifndef SVGA_MODE
+#define SVGA_MODE ASK_VGA
+#endif
+
+#ifndef RAMDISK
+#define RAMDISK 0
+#endif
+
+#ifndef ROOT_RDONLY
+#define ROOT_RDONLY 1
+#endif
+
+       .code16
+       .section ".bstext", "ax"
+
+       .global bootsect_start
+bootsect_start:
+
+       # Normalize the start address
+       ljmp    $BOOTSEG, $start2
+
+start2:
+       movw    %cs, %ax
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %ss
+       xorw    %sp, %sp
+       sti
+       cld
+
+       movw    $bugger_off_msg, %si
+
+msg_loop:
+       lodsb
+       andb    %al, %al
+       jz      bs_die
+       movb    $0xe, %ah
+       movw    $7, %bx
+       int     $0x10
+       jmp     msg_loop
+
+bs_die:
+       # Allow the user to press a key, then reboot
+       xorw    %ax, %ax
+       int     $0x16
+       int     $0x19
+
+       # int 0x19 should never return.  In case it does anyway,
+       # invoke the BIOS reset code...
+       ljmp    $0xf000,$0xfff0
+
+       .section ".bsdata", "a"
+bugger_off_msg:
+       .ascii  "Direct booting from floppy is no longer supported.\r\n"
+       .ascii  "Please use a boot loader program instead.\r\n"
+       .ascii  "\n"
+       .ascii  "Remove disk and press any key to reboot . . .\r\n"
+       .byte   0
+
+
+       # Kernel attributes; used by setup.  This is part 1 of the
+       # header, from the old boot sector.
+
+       .section ".header", "a"
+       .globl  hdr
+hdr:
+setup_sects:   .byte SETUPSECTS
+root_flags:    .word ROOT_RDONLY
+syssize:       .long SYSSIZE
+ram_size:      .word RAMDISK
+vid_mode:      .word SVGA_MODE
+root_dev:      .word ROOT_DEV
+boot_flag:     .word 0xAA55
+
+       # offset 512, entry point
+
+       .globl  _start
+_start:
+               # Explicitly enter this as bytes, or the assembler
+               # tries to generate a 3-byte jump here, which causes
+               # everything else to push off to the wrong offset.
+               .byte   0xeb            # short (2-byte) jump
+               .byte   start_of_setup-1f
+1:
+
+       # Part 2 of the header, from the old setup.S
+
+               .ascii  "HdrS"          # header signature
+               .word   0x0206          # header version number (>= 0x0105)
+                                       # or else old loadlin-1.5 will fail)
+               .globl realmode_swtch
+realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
+start_sys_seg: .word   SYSSEG
+               .word   kernel_version-512 # pointing to kernel version string
+                                       # above section of header is compatible
+                                       # with loadlin-1.5 (header v1.5). Don't
+                                       # change it.
+
+type_of_loader:        .byte   0               # = 0, old one (LILO, Loadlin,
+                                       #      Bootlin, SYSLX, bootsect...)
+                                       # See Documentation/i386/boot.txt for
+                                       # assigned ids
+
+# flags, unused bits must be zero (RFU) bit within loadflags
+loadflags:
+LOADED_HIGH    = 1                     # If set, the kernel is loaded high
+CAN_USE_HEAP   = 0x80                  # If set, the loader also has set
+                                       # heap_end_ptr to tell how much
+                                       # space behind setup.S can be used for
+                                       # heap purposes.
+                                       # Only the loader knows what is free
+#ifndef __BIG_KERNEL__
+               .byte   0
+#else
+               .byte   LOADED_HIGH
+#endif
+
+setup_move_size: .word  0x8000         # size to move, when setup is not
+                                       # loaded at 0x90000. We will move setup
+                                       # to 0x90000 then just before jumping
+                                       # into the kernel. However, only the
+                                       # loader knows how much data behind
+                                       # us also needs to be loaded.
+
+code32_start:                          # here loaders can put a different
+                                       # start address for 32-bit code.
+#ifndef __BIG_KERNEL__
+               .long   0x1000          #   0x1000 = default for zImage
+#else
+               .long   0x100000        # 0x100000 = default for big kernel
+#endif
+
+ramdisk_image: .long   0               # address of loaded ramdisk image
+                                       # Here the loader puts the 32-bit
+                                       # address where it loaded the image.
+                                       # This only will be read by the kernel.
+
+ramdisk_size:  .long   0               # its size in bytes
+
+bootsect_kludge:
+               .long   0               # obsolete
+
+heap_end_ptr:  .word   _end+1024       # (Header version 0x0201 or later)
+                                       # space from here (exclusive) down to
+                                       # end of setup code can be used by setup
+                                       # for local heap purposes.
+
+pad1:          .word   0
+cmd_line_ptr:  .long   0               # (Header version 0x0202 or later)
+                                       # If nonzero, a 32-bit pointer
+                                       # to the kernel command line.
+                                       # The command line should be
+                                       # located between the start of
+                                       # setup and the end of low
+                                       # memory (0xa0000), or it may
+                                       # get overwritten before it
+                                       # gets read.  If this field is
+                                       # used, there is no longer
+                                       # anything magical about the
+                                       # 0x90000 segment; the setup
+                                       # can be located anywhere in
+                                       # low memory 0x10000 or higher.
+
+ramdisk_max:   .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
+                                       # (Header version 0x0203 or later)
+                                       # The highest safe address for
+                                       # the contents of an initrd
+
+kernel_alignment:  .long CONFIG_PHYSICAL_ALIGN #physical addr alignment
+                                               #required for protected mode
+                                               #kernel
+#ifdef CONFIG_RELOCATABLE
+relocatable_kernel:    .byte 1
+#else
+relocatable_kernel:    .byte 0
+#endif
+pad2:                  .byte 0
+pad3:                  .word 0
+
+cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
+                                                #added with boot protocol
+                                                #version 2.06
+
+# End of setup header #####################################################
+
+       .section ".inittext", "ax"
+start_of_setup:
+#ifdef SAFE_RESET_DISK_CONTROLLER
+# Reset the disk controller.
+       movw    $0x0000, %ax            # Reset disk controller
+       movb    $0x80, %dl              # All disks
+       int     $0x13
+#endif
+
+# We will have entired with %cs = %ds+0x20, normalize %cs so
+# it is on par with the other segments.
+       pushw   %ds
+       pushw   $setup2
+       lretw
+
+setup2:
+# Force %es = %ds
+       movw    %ds, %ax
+       movw    %ax, %es
+       cld
+
+# Stack paranoia: align the stack and make sure it is good
+# for both 16- and 32-bit references.  In particular, if we
+# were meant to have been using the full 16-bit segment, the
+# caller might have set %sp to zero, which breaks %esp-based
+# references.
+       andw    $~3, %sp        # dword align (might as well...)
+       jnz     1f
+       movw    $0xfffc, %sp    # Make sure we're not zero
+1:     movzwl  %sp, %esp       # Clear upper half of %esp
+       sti
+
+# Check signature at end of setup
+       cmpl    $0x5a5aaa55, setup_sig
+       jne     setup_bad
+
+# Zero the bss
+       movw    $__bss_start, %di
+       movw    $_end+3, %cx
+       xorl    %eax, %eax
+       subw    %di, %cx
+       shrw    $2, %cx
+       rep; stosl
+
+# Jump to C code (should not return)
+       calll   main
+
+# Setup corrupt somehow...
+setup_bad:
+       movl    $setup_corrupt, %eax
+       calll   puts
+       # Fall through...
+
+       .globl  die
+       .type   die, @function
+die:
+       hlt
+       jmp     die
+
+       .size   die, .-due
+
+       .section ".initdata", "a"
+setup_corrupt:
+       .byte   7
+       .string "No setup signature found..."
diff --git a/arch/i386/boot/main.c b/arch/i386/boot/main.c
new file mode 100644 (file)
index 0000000..7f01f96
--- /dev/null
@@ -0,0 +1,161 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/main.c
+ *
+ * Main module for the real-mode kernel code
+ */
+
+#include "boot.h"
+
+struct boot_params boot_params __attribute__((aligned(16)));
+
+char *HEAP = _end;
+char *heap_end = _end;         /* Default end of heap = no heap */
+
+/*
+ * Copy the header into the boot parameter block.  Since this
+ * screws up the old-style command line protocol, adjust by
+ * filling in the new-style command line pointer instead.
+ */
+#define OLD_CL_MAGIC   0xA33F
+#define OLD_CL_ADDRESS 0x20
+
+static void copy_boot_params(void)
+{
+       struct old_cmdline {
+               u16 cl_magic;
+               u16 cl_offset;
+       };
+       const struct old_cmdline * const oldcmd =
+               (const struct old_cmdline *)OLD_CL_ADDRESS;
+
+       BUILD_BUG_ON(sizeof boot_params != 4096);
+       memcpy(&boot_params.hdr, &hdr, sizeof hdr);
+
+       if (!boot_params.hdr.cmd_line_ptr &&
+           oldcmd->cl_magic == OLD_CL_MAGIC) {
+               /* Old-style command line protocol. */
+               u16 cmdline_seg;
+
+               /* Figure out if the command line falls in the region
+                  of memory that an old kernel would have copied up
+                  to 0x90000... */
+               if (oldcmd->cl_offset < boot_params.hdr.setup_move_size)
+                       cmdline_seg = ds();
+               else
+                       cmdline_seg = 0x9000;
+
+               boot_params.hdr.cmd_line_ptr =
+                       (cmdline_seg << 4) + oldcmd->cl_offset;
+       }
+}
+
+/*
+ * Set the keyboard repeat rate to maximum.  Unclear why this
+ * is done here; this might be possible to kill off as stale code.
+ */
+static void keyboard_set_repeat(void)
+{
+       u16 ax = 0x0305;
+       u16 bx = 0;
+       asm volatile("int $0x16"
+                    : "+a" (ax), "+b" (bx)
+                    : : "ecx", "edx", "esi", "edi");
+}
+
+/*
+ * Get Intel SpeedStep IST information.
+ */
+static void query_speedstep_ist(void)
+{
+       asm("int $0x15"
+           : "=a" (boot_params.speedstep_info[0]),
+             "=b" (boot_params.speedstep_info[1]),
+             "=c" (boot_params.speedstep_info[2]),
+             "=d" (boot_params.speedstep_info[3])
+           : "a" (0x0000e980),  /* IST Support */
+             "d" (0x47534943)); /* Request value */
+}
+
+/*
+ * Tell the BIOS what CPU mode we intend to run in.
+ */
+static void set_bios_mode(void)
+{
+#ifdef CONFIG_X86_64
+       u32 eax, ebx;
+
+       eax = 0xec00;
+       ebx = 2;
+       asm volatile("int $0x15"
+                    : "+a" (eax), "+b" (ebx)
+                    : : "ecx", "edx", "esi", "edi");
+#endif
+}
+
+void main(void)
+{
+       /* First, copy the boot header into the "zeropage" */
+       copy_boot_params();
+
+       /* End of heap check */
+       if (boot_params.hdr.loadflags & CAN_USE_HEAP) {
+               heap_end = (char *)(boot_params.hdr.heap_end_ptr
+                                   +0x200-STACK_SIZE);
+       } else {
+               /* Boot protocol 2.00 only, no heap available */
+               puts("WARNING: Ancient bootloader, some functionality "
+                    "may be limited!\n");
+       }
+
+       /* Make sure we have all the proper CPU support */
+       if (validate_cpu()) {
+               puts("Unable to boot - please use a kernel appropriate "
+                    "for your CPU.\n");
+               die();
+       }
+
+       /* Tell the BIOS what CPU mode we intend to run in. */
+       set_bios_mode();
+
+       /* Detect memory layout */
+       detect_memory();
+
+       /* Set keyboard repeat rate (why?) */
+       keyboard_set_repeat();
+
+       /* Set the video mode */
+       set_video();
+
+       /* Query MCA information */
+       query_mca();
+
+       /* Voyager */
+#ifdef CONFIG_X86_VOYAGER
+       query_voyager();
+#endif
+
+       /* Query SpeedStep IST information */
+       query_speedstep_ist();
+
+       /* Query APM information */
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+       query_apm_bios();
+#endif
+
+       /* Query EDD information */
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+       query_edd();
+#endif
+       /* Do the last things and invoke protected mode */
+       go_to_protected_mode();
+}
diff --git a/arch/i386/boot/mca.c b/arch/i386/boot/mca.c
new file mode 100644 (file)
index 0000000..9b68bd1
--- /dev/null
@@ -0,0 +1,43 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/mca.c
+ *
+ * Get the MCA system description table
+ */
+
+#include "boot.h"
+
+int query_mca(void)
+{
+       u8 err;
+       u16 es, bx, len;
+
+       asm("pushw %%es ; "
+           "int $0x15 ; "
+           "setc %0 ; "
+           "movw %%es, %1 ; "
+           "popw %%es"
+           : "=acdSDm" (err), "=acdSDm" (es), "=b" (bx)
+           : "a" (0xc000));
+
+       if (err)
+               return -1;      /* No MCA present */
+
+       set_fs(es);
+       len = rdfs16(bx);
+
+       if (len > sizeof(boot_params.sys_desc_table))
+               len = sizeof(boot_params.sys_desc_table);
+
+       copy_from_fs(&boot_params.sys_desc_table, bx, len);
+       return 0;
+}
diff --git a/arch/i386/boot/memory.c b/arch/i386/boot/memory.c
new file mode 100644 (file)
index 0000000..1a2e62d
--- /dev/null
@@ -0,0 +1,99 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/memory.c
+ *
+ * Memory detection code
+ */
+
+#include "boot.h"
+
+#define SMAP   0x534d4150      /* ASCII "SMAP" */
+
+static int detect_memory_e820(void)
+{
+       u32 next = 0;
+       u32 size, id;
+       u8 err;
+       struct e820entry *desc = boot_params.e820_map;
+
+       do {
+               size = sizeof(struct e820entry);
+               id = SMAP;
+               asm("int $0x15; setc %0"
+                   : "=am" (err), "+b" (next), "+d" (id), "+c" (size),
+                     "=m" (*desc)
+                   : "D" (desc), "a" (0xe820));
+
+               if (err || id != SMAP)
+                       break;
+
+               boot_params.e820_entries++;
+               desc++;
+       } while (next && boot_params.e820_entries < E820MAX);
+
+       return boot_params.e820_entries;
+}
+
+static int detect_memory_e801(void)
+{
+       u16 ax, bx, cx, dx;
+       u8 err;
+
+       bx = cx = dx = 0;
+       ax = 0xe801;
+       asm("stc; int $0x15; setc %0"
+           : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx));
+
+       if (err)
+               return -1;
+
+       /* Do we really need to do this? */
+       if (cx || dx) {
+               ax = cx;
+               bx = dx;
+       }
+
+       if (ax > 15*1024)
+               return -1;      /* Bogus! */
+
+       /* This ignores memory above 16MB if we have a memory hole
+          there.  If someone actually finds a machine with a memory
+          hole at 16MB and no support for 0E820h they should probably
+          generate a fake e820 map. */
+       boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax;
+
+       return 0;
+}
+
+static int detect_memory_88(void)
+{
+       u16 ax;
+       u8 err;
+
+       ax = 0x8800;
+       asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax));
+
+       boot_params.screen_info.ext_mem_k = ax;
+
+       return -err;
+}
+
+int detect_memory(void)
+{
+       if (detect_memory_e820() > 0)
+               return 0;
+
+       if (!detect_memory_e801())
+               return 0;
+
+       return detect_memory_88();
+}
diff --git a/arch/i386/boot/pm.c b/arch/i386/boot/pm.c
new file mode 100644 (file)
index 0000000..3fa53e1
--- /dev/null
@@ -0,0 +1,170 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/pm.c
+ *
+ * Prepare the machine for transition to protected mode.
+ */
+
+#include "boot.h"
+#include <asm/segment.h>
+
+/*
+ * Invoke the realmode switch hook if present; otherwise
+ * disable all interrupts.
+ */
+static void realmode_switch_hook(void)
+{
+       if (boot_params.hdr.realmode_swtch) {
+               asm volatile("lcallw *%0"
+                            : : "m" (boot_params.hdr.realmode_swtch)
+                            : "eax", "ebx", "ecx", "edx");
+       } else {
+               asm volatile("cli");
+               outb(0x80, 0x70); /* Disable NMI */
+               io_delay();
+       }
+}
+
+/*
+ * A zImage kernel is loaded at 0x10000 but wants to run at 0x1000.
+ * A bzImage kernel is loaded and runs at 0x100000.
+ */
+static void move_kernel_around(void)
+{
+       /* Note: rely on the compile-time option here rather than
+          the LOADED_HIGH flag.  The Qemu kernel loader unconditionally
+          sets the loadflags to zero. */
+#ifndef __BIG_KERNEL__
+       u16 dst_seg, src_seg;
+       u32 syssize;
+
+       dst_seg =  0x1000 >> 4;
+       src_seg = 0x10000 >> 4;
+       syssize = boot_params.hdr.syssize; /* Size in 16-byte paragraphs */
+
+       while (syssize) {
+               int paras  = (syssize >= 0x1000) ? 0x1000 : syssize;
+               int dwords = paras << 2;
+
+               asm volatile("pushw %%es ; "
+                            "pushw %%ds ; "
+                            "movw %1,%%es ; "
+                            "movw %2,%%ds ; "
+                            "xorw %%di,%%di ; "
+                            "xorw %%si,%%si ; "
+                            "rep;movsl ; "
+                            "popw %%ds ; "
+                            "popw %%es"
+                            : "+c" (dwords)
+                            : "rm" (dst_seg), "rm" (src_seg)
+                            : "esi", "edi");
+
+               syssize -= paras;
+               dst_seg += paras;
+               src_seg += paras;
+       }
+#endif
+}
+
+/*
+ * Disable all interrupts at the legacy PIC.
+ */
+static void mask_all_interrupts(void)
+{
+       outb(0xff, 0xa1);       /* Mask all interrupts on the seconday PIC */
+       io_delay();
+       outb(0xfb, 0x21);       /* Mask all but cascade on the primary PIC */
+       io_delay();
+}
+
+/*
+ * Reset IGNNE# if asserted in the FPU.
+ */
+static void reset_coprocessor(void)
+{
+       outb(0, 0xf0);
+       io_delay();
+       outb(0, 0xf1);
+       io_delay();
+}
+
+/*
+ * Set up the GDT
+ */
+#define GDT_ENTRY(flags,base,limit)            \
+       (((u64)(base & 0xff000000) << 32) |     \
+        ((u64)flags << 40) |                   \
+        ((u64)(limit & 0x00ff0000) << 32) |    \
+        ((u64)(base & 0x00ffff00) << 16) |     \
+        ((u64)(limit & 0x0000ffff)))
+
+struct gdt_ptr {
+       u16 len;
+       u32 ptr;
+} __attribute__((packed));
+
+static void setup_gdt(void)
+{
+       /* There are machines which are known to not boot with the GDT
+          being 8-byte unaligned.  Intel recommends 16 byte alignment. */
+       static const u64 boot_gdt[] __attribute__((aligned(16))) = {
+               /* CS: code, read/execute, 4 GB, base 0 */
+               [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
+               /* DS: data, read/write, 4 GB, base 0 */
+               [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
+       };
+       struct gdt_ptr gdt;
+
+       gdt.len = sizeof(boot_gdt)-1;
+       gdt.ptr = (u32)&boot_gdt + (ds() << 4);
+
+       asm volatile("lgdtl %0" : : "m" (gdt));
+}
+
+/*
+ * Set up the IDT
+ */
+static void setup_idt(void)
+{
+       static const struct gdt_ptr null_idt = {0, 0};
+       asm volatile("lidtl %0" : : "m" (null_idt));
+}
+
+/*
+ * Actual invocation sequence
+ */
+void go_to_protected_mode(void)
+{
+       /* Hook before leaving real mode, also disables interrupts */
+       realmode_switch_hook();
+
+       /* Move the kernel/setup to their final resting places */
+       move_kernel_around();
+
+       /* Enable the A20 gate */
+       if (enable_a20()) {
+               puts("A20 gate not responding, unable to boot...\n");
+               die();
+       }
+
+       /* Reset coprocessor (IGNNE#) */
+       reset_coprocessor();
+
+       /* Mask all interrupts in the PIC */
+       mask_all_interrupts();
+
+       /* Actual transition to protected mode... */
+       setup_idt();
+       setup_gdt();
+       protected_mode_jump(boot_params.hdr.code32_start,
+                           (u32)&boot_params + (ds() << 4));
+}
diff --git a/arch/i386/boot/pmjump.S b/arch/i386/boot/pmjump.S
new file mode 100644 (file)
index 0000000..2e55923
--- /dev/null
@@ -0,0 +1,54 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/pmjump.S
+ *
+ * The actual transition into protected mode
+ */
+
+#include <asm/boot.h>
+#include <asm/segment.h>
+
+       .text
+
+       .globl  protected_mode_jump
+       .type   protected_mode_jump, @function
+
+       .code16
+
+/*
+ * void protected_mode_jump(u32 entrypoint, u32 bootparams);
+ */
+protected_mode_jump:
+       xorl    %ebx, %ebx              # Flag to indicate this is a boot
+       movl    %edx, %esi              # Pointer to boot_params table
+       movl    %eax, 2f                # Patch ljmpl instruction
+       jmp     1f                      # Short jump to flush instruction q.
+
+1:
+       movw    $__BOOT_DS, %cx
+
+       movl    %cr0, %edx
+       orb     $1, %dl                 # Protected mode (PE) bit
+       movl    %edx, %cr0
+
+       movw    %cx, %ds
+       movw    %cx, %es
+       movw    %cx, %fs
+       movw    %cx, %gs
+       movw    %cx, %ss
+
+       # Jump to the 32-bit entrypoint
+       .byte   0x66, 0xea              # ljmpl opcode
+2:     .long   0                       # offset
+       .word   __BOOT_CS               # segment
+
+       .size   protected_mode_jump, .-protected_mode_jump
diff --git a/arch/i386/boot/printf.c b/arch/i386/boot/printf.c
new file mode 100644 (file)
index 0000000..1a09f93
--- /dev/null
@@ -0,0 +1,307 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/printf.c
+ *
+ * Oh, it's a waste of space, but oh-so-yummy for debugging.  This
+ * version of printf() does not include 64-bit support.  "Live with
+ * it."
+ *
+ */
+
+#include "boot.h"
+
+static int skip_atoi(const char **s)
+{
+       int i = 0;
+
+       while (isdigit(**s))
+               i = i * 10 + *((*s)++) - '0';
+       return i;
+}
+
+#define ZEROPAD        1               /* pad with zero */
+#define SIGN   2               /* unsigned/signed long */
+#define PLUS   4               /* show plus */
+#define SPACE  8               /* space if plus */
+#define LEFT   16              /* left justified */
+#define SPECIAL        32              /* 0x */
+#define LARGE  64              /* use 'ABCDEF' instead of 'abcdef' */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+static char *number(char *str, long num, int base, int size, int precision,
+                   int type)
+{
+       char c, sign, tmp[66];
+       const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+       int i;
+
+       if (type & LARGE)
+               digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+       if (type & LEFT)
+               type &= ~ZEROPAD;
+       if (base < 2 || base > 36)
+               return 0;
+       c = (type & ZEROPAD) ? '0' : ' ';
+       sign = 0;
+       if (type & SIGN) {
+               if (num < 0) {
+                       sign = '-';
+                       num = -num;
+                       size--;
+               } else if (type & PLUS) {
+                       sign = '+';
+                       size--;
+               } else if (type & SPACE) {
+                       sign = ' ';
+                       size--;
+               }
+       }
+       if (type & SPECIAL) {
+               if (base == 16)
+                       size -= 2;
+               else if (base == 8)
+                       size--;
+       }
+       i = 0;
+       if (num == 0)
+               tmp[i++] = '0';
+       else
+               while (num != 0)
+                       tmp[i++] = digits[do_div(num, base)];
+       if (i > precision)
+               precision = i;
+       size -= precision;
+       if (!(type & (ZEROPAD + LEFT)))
+               while (size-- > 0)
+                       *str++ = ' ';
+       if (sign)
+               *str++ = sign;
+       if (type & SPECIAL) {
+               if (base == 8)
+                       *str++ = '0';
+               else if (base == 16) {
+                       *str++ = '0';
+                       *str++ = digits[33];
+               }
+       }
+       if (!(type & LEFT))
+               while (size-- > 0)
+                       *str++ = c;
+       while (i < precision--)
+               *str++ = '0';
+       while (i-- > 0)
+               *str++ = tmp[i];
+       while (size-- > 0)
+               *str++ = ' ';
+       return str;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+       int len;
+       unsigned long num;
+       int i, base;
+       char *str;
+       const char *s;
+
+       int flags;              /* flags to number() */
+
+       int field_width;        /* width of output field */
+       int precision;          /* min. # of digits for integers; max
+                                  number of chars for from string */
+       int qualifier;          /* 'h', 'l', or 'L' for integer fields */
+
+       for (str = buf; *fmt; ++fmt) {
+               if (*fmt != '%') {
+                       *str++ = *fmt;
+                       continue;
+               }
+
+               /* process flags */
+               flags = 0;
+             repeat:
+               ++fmt;          /* this also skips first '%' */
+               switch (*fmt) {
+               case '-':
+                       flags |= LEFT;
+                       goto repeat;
+               case '+':
+                       flags |= PLUS;
+                       goto repeat;
+               case ' ':
+                       flags |= SPACE;
+                       goto repeat;
+               case '#':
+                       flags |= SPECIAL;
+                       goto repeat;
+               case '0':
+                       flags |= ZEROPAD;
+                       goto repeat;
+               }
+
+               /* get field width */
+               field_width = -1;
+               if (isdigit(*fmt))
+                       field_width = skip_atoi(&fmt);
+               else if (*fmt == '*') {
+                       ++fmt;
+                       /* it's the next argument */
+                       field_width = va_arg(args, int);
+                       if (field_width < 0) {
+                               field_width = -field_width;
+                               flags |= LEFT;
+                       }
+               }
+
+               /* get the precision */
+               precision = -1;
+               if (*fmt == '.') {
+                       ++fmt;
+                       if (isdigit(*fmt))
+                               precision = skip_atoi(&fmt);
+                       else if (*fmt == '*') {
+                               ++fmt;
+                               /* it's the next argument */
+                               precision = va_arg(args, int);
+                       }
+                       if (precision < 0)
+                               precision = 0;
+               }
+
+               /* get the conversion qualifier */
+               qualifier = -1;
+               if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+                       qualifier = *fmt;
+                       ++fmt;
+               }
+
+               /* default base */
+               base = 10;
+
+               switch (*fmt) {
+               case 'c':
+                       if (!(flags & LEFT))
+                               while (--field_width > 0)
+                                       *str++ = ' ';
+                       *str++ = (unsigned char)va_arg(args, int);
+                       while (--field_width > 0)
+                               *str++ = ' ';
+                       continue;
+
+               case 's':
+                       s = va_arg(args, char *);
+                       len = strnlen(s, precision);
+
+                       if (!(flags & LEFT))
+                               while (len < field_width--)
+                                       *str++ = ' ';
+                       for (i = 0; i < len; ++i)
+                               *str++ = *s++;
+                       while (len < field_width--)
+                               *str++ = ' ';
+                       continue;
+
+               case 'p':
+                       if (field_width == -1) {
+                               field_width = 2 * sizeof(void *);
+                               flags |= ZEROPAD;
+                       }
+                       str = number(str,
+                                    (unsigned long)va_arg(args, void *), 16,
+                                    field_width, precision, flags);
+                       continue;
+
+               case 'n':
+                       if (qualifier == 'l') {
+                               long *ip = va_arg(args, long *);
+                               *ip = (str - buf);
+                       } else {
+                               int *ip = va_arg(args, int *);
+                               *ip = (str - buf);
+                       }
+                       continue;
+
+               case '%':
+                       *str++ = '%';
+                       continue;
+
+                       /* integer number formats - set up the flags and "break" */
+               case 'o':
+                       base = 8;
+                       break;
+
+               case 'X':
+                       flags |= LARGE;
+               case 'x':
+                       base = 16;
+                       break;
+
+               case 'd':
+               case 'i':
+                       flags |= SIGN;
+               case 'u':
+                       break;
+
+               default:
+                       *str++ = '%';
+                       if (*fmt)
+                               *str++ = *fmt;
+                       else
+                               --fmt;
+                       continue;
+               }
+               if (qualifier == 'l')
+                       num = va_arg(args, unsigned long);
+               else if (qualifier == 'h') {
+                       num = (unsigned short)va_arg(args, int);
+                       if (flags & SIGN)
+                               num = (short)num;
+               } else if (flags & SIGN)
+                       num = va_arg(args, int);
+               else
+                       num = va_arg(args, unsigned int);
+               str = number(str, num, base, field_width, precision, flags);
+       }
+       *str = '\0';
+       return str - buf;
+}
+
+int sprintf(char *buf, const char *fmt, ...)
+{
+       va_list args;
+       int i;
+
+       va_start(args, fmt);
+       i = vsprintf(buf, fmt, args);
+       va_end(args);
+       return i;
+}
+
+int printf(const char *fmt, ...)
+{
+       char printf_buf[1024];
+       va_list args;
+       int printed;
+
+       va_start(args, fmt);
+       printed = vsprintf(printf_buf, fmt, args);
+       va_end(args);
+
+       puts(printf_buf);
+
+       return printed;
+}
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
deleted file mode 100644 (file)
index 6dbcc95..0000000
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*
- *     setup.S         Copyright (C) 1991, 1992 Linus Torvalds
- *
- * setup.s is responsible for getting the system data from the BIOS,
- * and putting them into the appropriate places in system memory.
- * both setup.s and system has been loaded by the bootblock.
- *
- * This code asks the bios for memory/disk/other parameters, and
- * puts them in a "safe" place: 0x90000-0x901FF, ie where the
- * boot-block used to be. It is then up to the protected mode
- * system to read them from there before the area is overwritten
- * for buffer-blocks.
- *
- * Move PS/2 aux init code to psaux.c
- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
- *
- * some changes and additional features by Christoph Niemann,
- * March 1993/June 1994 (Christoph.Niemann@linux.org)
- *
- * add APM BIOS checking by Stephen Rothwell, May 1994
- * (sfr@canb.auug.org.au)
- *
- * High load stuff, initrd support and position independency
- * by Hans Lermen & Werner Almesberger, February 1996
- * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
- *
- * Video handling moved to video.S by Martin Mares, March 1996
- * <mj@k332.feld.cvut.cz>
- *
- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
- * parsons) to avoid loadlin confusion, July 1997
- *
- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
- * <stiker@northlink.com>
- *
- * Fix to work around buggy BIOSes which don't use carry bit correctly
- * and/or report extended memory in CX/DX for e801h memory size detection 
- * call.  As a result the kernel got wrong figures.  The int15/e801h docs
- * from Ralf Brown interrupt list seem to indicate AX/BX should be used
- * anyway.  So to avoid breaking many machines (presumably there was a reason
- * to orginally use CX/DX instead of AX/BX), we do a kludge to see
- * if CX/DX have been changed in the e801 call and if so use AX/BX .
- * Michael Miller, April 2001 <michaelm@mjmm.org>
- *
- * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
- * by Robert Schwebel, December 2001 <robert@schwebel.de>
- */
-
-#include <asm/segment.h>
-#include <linux/utsrelease.h>
-#include <linux/compile.h>
-#include <asm/boot.h>
-#include <asm/e820.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-       
-/* Signature words to ensure LILO loaded us right */
-#define SIG1   0xAA55
-#define SIG2   0x5A5A
-
-INITSEG  = DEF_INITSEG         # 0x9000, we move boot here, out of the way
-SYSSEG   = DEF_SYSSEG          # 0x1000, system loaded at 0x10000 (65536).
-SETUPSEG = DEF_SETUPSEG                # 0x9020, this is the current segment
-                               # ... and the former contents of CS
-
-DELTA_INITSEG = SETUPSEG - INITSEG     # 0x0020
-
-.code16
-.globl begtext, begdata, begbss, endtext, enddata, endbss
-
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
-
-start:
-       jmp     trampoline
-
-# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
-
-               .ascii  "HdrS"          # header signature
-               .word   0x0206          # header version number (>= 0x0105)
-                                       # or else old loadlin-1.5 will fail)
-realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
-start_sys_seg: .word   SYSSEG
-               .word   kernel_version  # pointing to kernel version string
-                                       # above section of header is compatible
-                                       # with loadlin-1.5 (header v1.5). Don't
-                                       # change it.
-
-type_of_loader:        .byte   0               # = 0, old one (LILO, Loadlin,
-                                       #      Bootlin, SYSLX, bootsect...)
-                                       # See Documentation/i386/boot.txt for
-                                       # assigned ids
-       
-# flags, unused bits must be zero (RFU) bit within loadflags
-loadflags:
-LOADED_HIGH    = 1                     # If set, the kernel is loaded high
-CAN_USE_HEAP   = 0x80                  # If set, the loader also has set
-                                       # heap_end_ptr to tell how much
-                                       # space behind setup.S can be used for
-                                       # heap purposes.
-                                       # Only the loader knows what is free
-#ifndef __BIG_KERNEL__
-               .byte   0
-#else
-               .byte   LOADED_HIGH
-#endif
-
-setup_move_size: .word  0x8000         # size to move, when setup is not
-                                       # loaded at 0x90000. We will move setup 
-                                       # to 0x90000 then just before jumping
-                                       # into the kernel. However, only the
-                                       # loader knows how much data behind
-                                       # us also needs to be loaded.
-
-code32_start:                          # here loaders can put a different
-                                       # start address for 32-bit code.
-#ifndef __BIG_KERNEL__
-               .long   0x1000          #   0x1000 = default for zImage
-#else
-               .long   0x100000        # 0x100000 = default for big kernel
-#endif
-
-ramdisk_image: .long   0               # address of loaded ramdisk image
-                                       # Here the loader puts the 32-bit
-                                       # address where it loaded the image.
-                                       # This only will be read by the kernel.
-
-ramdisk_size:  .long   0               # its size in bytes
-
-bootsect_kludge:
-               .long   0               # obsolete
-
-heap_end_ptr:  .word   modelist+1024   # (Header version 0x0201 or later)
-                                       # space from here (exclusive) down to
-                                       # end of setup code can be used by setup
-                                       # for local heap purposes.
-
-pad1:          .word   0
-cmd_line_ptr:  .long 0                 # (Header version 0x0202 or later)
-                                       # If nonzero, a 32-bit pointer
-                                       # to the kernel command line.
-                                       # The command line should be
-                                       # located between the start of
-                                       # setup and the end of low
-                                       # memory (0xa0000), or it may
-                                       # get overwritten before it
-                                       # gets read.  If this field is
-                                       # used, there is no longer
-                                       # anything magical about the
-                                       # 0x90000 segment; the setup
-                                       # can be located anywhere in
-                                       # low memory 0x10000 or higher.
-
-ramdisk_max:   .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
-                                       # (Header version 0x0203 or later)
-                                       # The highest safe address for
-                                       # the contents of an initrd
-
-kernel_alignment:  .long CONFIG_PHYSICAL_ALIGN         #physical addr alignment
-                                               #required for protected mode
-                                               #kernel
-#ifdef CONFIG_RELOCATABLE
-relocatable_kernel:    .byte 1
-#else
-relocatable_kernel:    .byte 0
-#endif
-pad2:                  .byte 0
-pad3:                  .word 0
-
-cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
-                                                #added with boot protocol
-                                                #version 2.06
-
-trampoline:    call    start_of_setup
-               .align 16
-                                       # The offset at this point is 0x240
-               .space  (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff)
-# End of setup header #####################################################
-
-start_of_setup:
-# Bootlin depends on this being done early
-       movw    $0x01500, %ax
-       movb    $0x81, %dl
-       int     $0x13
-
-#ifdef SAFE_RESET_DISK_CONTROLLER
-# Reset the disk controller.
-       movw    $0x0000, %ax
-       movb    $0x80, %dl
-       int     $0x13
-#endif
-
-# Set %ds = %cs, we know that SETUPSEG = %cs at this point
-       movw    %cs, %ax                # aka SETUPSEG
-       movw    %ax, %ds
-# Check signature at end of setup
-       cmpw    $SIG1, setup_sig1
-       jne     bad_sig
-
-       cmpw    $SIG2, setup_sig2
-       jne     bad_sig
-
-       jmp     good_sig1
-
-# Routine to print asciiz string at ds:si
-prtstr:
-       lodsb
-       andb    %al, %al
-       jz      fin
-
-       call    prtchr
-       jmp     prtstr
-
-fin:   ret
-
-# Space printing
-prtsp2:        call    prtspc          # Print double space
-prtspc:        movb    $0x20, %al      # Print single space (note: fall-thru)
-
-# Part of above routine, this one just prints ascii al
-prtchr:        pushw   %ax
-       pushw   %cx
-       movw    $7,%bx
-       movw    $0x01, %cx
-       movb    $0x0e, %ah
-       int     $0x10
-       popw    %cx
-       popw    %ax
-       ret
-
-beep:  movb    $0x07, %al
-       jmp     prtchr
-       
-no_sig_mess: .string   "No setup signature found ..."
-
-good_sig1:
-       jmp     good_sig
-
-# We now have to find the rest of the setup code/data
-bad_sig:
-       movw    %cs, %ax                        # SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # INITSEG
-       movw    %ax, %ds
-       xorb    %bh, %bh
-       movb    (497), %bl                      # get setup sect from bootsect
-       subw    $4, %bx                         # LILO loads 4 sectors of setup
-       shlw    $8, %bx                         # convert to words (1sect=2^8 words)
-       movw    %bx, %cx
-       shrw    $3, %bx                         # convert to segment
-       addw    $SYSSEG, %bx
-       movw    %bx, %cs:start_sys_seg
-# Move rest of setup code/data to here
-       movw    $2048, %di                      # four sectors loaded by LILO
-       subw    %si, %si
-       pushw   %cs
-       popw    %es
-       movw    $SYSSEG, %ax
-       movw    %ax, %ds
-       rep
-       movsw
-       movw    %cs, %ax                        # aka SETUPSEG
-       movw    %ax, %ds
-       cmpw    $SIG1, setup_sig1
-       jne     no_sig
-
-       cmpw    $SIG2, setup_sig2
-       jne     no_sig
-
-       jmp     good_sig
-
-no_sig:
-       lea     no_sig_mess, %si
-       call    prtstr
-
-no_sig_loop:
-       hlt
-       jmp     no_sig_loop
-
-good_sig:
-       movw    %cs, %ax                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       movw    %ax, %ds
-# Check if an old loader tries to load a big-kernel
-       testb   $LOADED_HIGH, %cs:loadflags     # Do we have a big kernel?
-       jz      loader_ok                       # No, no danger for old loaders.
-
-       cmpb    $0, %cs:type_of_loader          # Do we have a loader that
-                                               # can deal with us?
-       jnz     loader_ok                       # Yes, continue.
-
-       pushw   %cs                             # No, we have an old loader,
-       popw    %ds                             # die. 
-       lea     loader_panic_mess, %si
-       call    prtstr
-
-       jmp     no_sig_loop
-
-loader_panic_mess: .string "Wrong loader, giving up..."
-
-# check minimum cpuid
-# we do this here because it is the last place we can actually
-# show a user visible error message. Later the video modus
-# might be already messed up.
-loader_ok:
-       call verify_cpu
-       testl  %eax,%eax
-       jz      cpu_ok
-       movw    %cs,%ax         # aka SETUPSEG
-       movw    %ax,%ds
-       lea     cpu_panic_mess,%si
-       call    prtstr
-1:     jmp     1b
-
-cpu_panic_mess:
-       .asciz  "PANIC: CPU too old for this kernel."
-
-#include "../kernel/verify_cpu.S"
-
-cpu_ok:
-# Get memory size (extended mem, kB)
-
-       xorl    %eax, %eax
-       movl    %eax, (0x1e0)
-#ifndef STANDARD_MEMORY_BIOS_CALL
-       movb    %al, (E820NR)
-# Try three different memory detection schemes.  First, try
-# e820h, which lets us assemble a memory map, then try e801h,
-# which returns a 32-bit memory size, and finally 88h, which
-# returns 0-64m
-
-# method E820H:
-# the memory map from hell.  e820h returns memory classified into
-# a whole bunch of different types, and allows memory holes and
-# everything.  We scan through this memory map and build a list
-# of the first 32 memory areas, which we return at [E820MAP].
-# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.
-
-#define SMAP  0x534d4150
-
-meme820:
-       xorl    %ebx, %ebx                      # continuation counter
-       movw    $E820MAP, %di                   # point into the whitelist
-                                               # so we can have the bios
-                                               # directly write into it.
-
-jmpe820:
-       movl    $0x0000e820, %eax               # e820, upper word zeroed
-       movl    $SMAP, %edx                     # ascii 'SMAP'
-       movl    $20, %ecx                       # size of the e820rec
-       pushw   %ds                             # data record.
-       popw    %es
-       int     $0x15                           # make the call
-       jc      bail820                         # fall to e801 if it fails
-
-       cmpl    $SMAP, %eax                     # check the return is `SMAP'
-       jne     bail820                         # fall to e801 if it fails
-
-#      cmpl    $1, 16(%di)                     # is this usable memory?
-#      jne     again820
-
-       # If this is usable memory, we save it by simply advancing %di by
-       # sizeof(e820rec).
-       #
-good820:
-       movb    (E820NR), %al                   # up to 128 entries
-       cmpb    $E820MAX, %al
-       jae     bail820
-
-       incb    (E820NR)
-       movw    %di, %ax
-       addw    $20, %ax
-       movw    %ax, %di
-again820:
-       cmpl    $0, %ebx                        # check to see if
-       jne     jmpe820                         # %ebx is set to EOF
-bail820:
-
-
-# method E801H:
-# memory size is in 1k chunksizes, to avoid confusing loadlin.
-# we store the 0xe801 memory size in a completely different place,
-# because it will most likely be longer than 16 bits.
-# (use 1e0 because that's what Larry Augustine uses in his
-# alternative new memory detection scheme, and it's sensible
-# to write everything into the same place.)
-
-meme801:
-       stc                                     # fix to work around buggy
-       xorw    %cx,%cx                         # BIOSes which don't clear/set
-       xorw    %dx,%dx                         # carry on pass/error of
-                                               # e801h memory size call
-                                               # or merely pass cx,dx though
-                                               # without changing them.
-       movw    $0xe801, %ax
-       int     $0x15
-       jc      mem88
-
-       cmpw    $0x0, %cx                       # Kludge to handle BIOSes
-       jne     e801usecxdx                     # which report their extended
-       cmpw    $0x0, %dx                       # memory in AX/BX rather than
-       jne     e801usecxdx                     # CX/DX.  The spec I have read
-       movw    %ax, %cx                        # seems to indicate AX/BX 
-       movw    %bx, %dx                        # are more reasonable anyway...
-
-e801usecxdx:
-       andl    $0xffff, %edx                   # clear sign extend
-       shll    $6, %edx                        # and go from 64k to 1k chunks
-       movl    %edx, (0x1e0)                   # store extended memory size
-       andl    $0xffff, %ecx                   # clear sign extend
-       addl    %ecx, (0x1e0)                   # and add lower memory into
-                                               # total size.
-
-# Ye Olde Traditional Methode.  Returns the memory size (up to 16mb or
-# 64mb, depending on the bios) in ax.
-mem88:
-
-#endif
-       movb    $0x88, %ah
-       int     $0x15
-       movw    %ax, (2)
-
-# Set the keyboard repeat rate to the max
-       movw    $0x0305, %ax
-       xorw    %bx, %bx
-       int     $0x16
-
-# Check for video adapter and its parameters and allow the
-# user to browse video modes.
-       call    video                           # NOTE: we need %ds pointing
-                                               # to bootsector
-
-# Get hd0 data...
-       xorw    %ax, %ax
-       movw    %ax, %ds
-       ldsw    (4 * 0x41), %si
-       movw    %cs, %ax                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       pushw   %ax
-       movw    %ax, %es
-       movw    $0x0080, %di
-       movw    $0x10, %cx
-       pushw   %cx
-       cld
-       rep
-       movsb
-# Get hd1 data...
-       xorw    %ax, %ax
-       movw    %ax, %ds
-       ldsw    (4 * 0x46), %si
-       popw    %cx
-       popw    %es
-       movw    $0x0090, %di
-       rep
-       movsb
-# Check that there IS a hd1 :-)
-       movw    $0x01500, %ax
-       movb    $0x81, %dl
-       int     $0x13
-       jc      no_disk1
-       
-       cmpb    $3, %ah
-       je      is_disk1
-
-no_disk1:
-       movw    %cs, %ax                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       movw    %ax, %es
-       movw    $0x0090, %di
-       movw    $0x10, %cx
-       xorw    %ax, %ax
-       cld
-       rep
-       stosb
-is_disk1:
-# check for Micro Channel (MCA) bus
-       movw    %cs, %ax                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       movw    %ax, %ds
-       xorw    %ax, %ax
-       movw    %ax, (0xa0)                     # set table length to 0
-       movb    $0xc0, %ah
-       stc
-       int     $0x15                           # moves feature table to es:bx
-       jc      no_mca
-
-       pushw   %ds
-       movw    %es, %ax
-       movw    %ax, %ds
-       movw    %cs, %ax                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       movw    %ax, %es
-       movw    %bx, %si
-       movw    $0xa0, %di
-       movw    (%si), %cx
-       addw    $2, %cx                         # table length is a short
-       cmpw    $0x10, %cx
-       jc      sysdesc_ok
-
-       movw    $0x10, %cx                      # we keep only first 16 bytes
-sysdesc_ok:
-       rep
-       movsb
-       popw    %ds
-no_mca:
-#ifdef CONFIG_X86_VOYAGER
-       movb    $0xff, 0x40     # flag on config found
-       movb    $0xc0, %al
-       mov     $0xff, %ah
-       int     $0x15           # put voyager config info at es:di
-       jc      no_voyager
-       movw    $0x40, %si      # place voyager info in apm table
-       cld
-       movw    $7, %cx
-voyager_rep:
-       movb    %es:(%di), %al
-       movb    %al,(%si)
-       incw    %di
-       incw    %si
-       decw    %cx
-       jnz     voyager_rep
-no_voyager:    
-#endif
-# Check for PS/2 pointing device
-       movw    %cs, %ax                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       movw    %ax, %ds
-       movb    $0, (0x1ff)                     # default is no pointing device
-       int     $0x11                           # int 0x11: equipment list
-       testb   $0x04, %al                      # check if mouse installed
-       jz      no_psmouse
-
-       movb    $0xAA, (0x1ff)                  # device present
-no_psmouse:
-
-#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
-       movl    $0x0000E980, %eax               # IST Support 
-       movl    $0x47534943, %edx               # Request value
-       int     $0x15
-
-       movl    %eax, (96)
-       movl    %ebx, (100)
-       movl    %ecx, (104)
-       movl    %edx, (108)
-#endif
-
-#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
-# Then check for an APM BIOS...
-                                               # %ds points to the bootsector
-       movw    $0, 0x40                        # version = 0 means no APM BIOS
-       movw    $0x05300, %ax                   # APM BIOS installation check
-       xorw    %bx, %bx
-       int     $0x15
-       jc      done_apm_bios                   # Nope, no APM BIOS
-       
-       cmpw    $0x0504d, %bx                   # Check for "PM" signature
-       jne     done_apm_bios                   # No signature, no APM BIOS
-
-       andw    $0x02, %cx                      # Is 32 bit supported?
-       je      done_apm_bios                   # No 32-bit, no (good) APM BIOS
-
-       movw    $0x05304, %ax                   # Disconnect first just in case
-       xorw    %bx, %bx
-       int     $0x15                           # ignore return code
-       movw    $0x05303, %ax                   # 32 bit connect
-       xorl    %ebx, %ebx
-       xorw    %cx, %cx                        # paranoia :-)
-       xorw    %dx, %dx                        #   ...
-       xorl    %esi, %esi                      #   ...
-       xorw    %di, %di                        #   ...
-       int     $0x15
-       jc      no_32_apm_bios                  # Ack, error. 
-
-       movw    %ax,  (66)                      # BIOS code segment
-       movl    %ebx, (68)                      # BIOS entry point offset
-       movw    %cx,  (72)                      # BIOS 16 bit code segment
-       movw    %dx,  (74)                      # BIOS data segment
-       movl    %esi, (78)                      # BIOS code segment lengths
-       movw    %di,  (82)                      # BIOS data segment length
-# Redo the installation check as the 32 bit connect
-# modifies the flags returned on some BIOSs
-       movw    $0x05300, %ax                   # APM BIOS installation check
-       xorw    %bx, %bx
-       xorw    %cx, %cx                        # paranoia
-       int     $0x15
-       jc      apm_disconnect                  # error -> shouldn't happen
-
-       cmpw    $0x0504d, %bx                   # check for "PM" signature
-       jne     apm_disconnect                  # no sig -> shouldn't happen
-
-       movw    %ax, (64)                       # record the APM BIOS version
-       movw    %cx, (76)                       # and flags
-       jmp     done_apm_bios
-
-apm_disconnect:                                        # Tidy up
-       movw    $0x05304, %ax                   # Disconnect
-       xorw    %bx, %bx
-       int     $0x15                           # ignore return code
-
-       jmp     done_apm_bios
-
-no_32_apm_bios:
-       andw    $0xfffd, (76)                   # remove 32 bit support bit
-done_apm_bios:
-#endif
-
-#include "edd.S"
-
-# Now we want to move to protected mode ...
-       cmpw    $0, %cs:realmode_swtch
-       jz      rmodeswtch_normal
-
-       lcall   *%cs:realmode_swtch
-
-       jmp     rmodeswtch_end
-
-rmodeswtch_normal:
-        pushw  %cs
-       call    default_switch
-
-rmodeswtch_end:
-# Now we move the system to its rightful place ... but we check if we have a
-# big-kernel. In that case we *must* not move it ...
-       testb   $LOADED_HIGH, %cs:loadflags
-       jz      do_move0                        # .. then we have a normal low
-                                               # loaded zImage
-                                               # .. or else we have a high
-                                               # loaded bzImage
-       jmp     end_move                        # ... and we skip moving
-
-do_move0:
-       movw    $0x100, %ax                     # start of destination segment
-       movw    %cs, %bp                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %bp             # aka INITSEG
-       movw    %cs:start_sys_seg, %bx          # start of source segment
-       cld
-do_move:
-       movw    %ax, %es                        # destination segment
-       incb    %ah                             # instead of add ax,#0x100
-       movw    %bx, %ds                        # source segment
-       addw    $0x100, %bx
-       subw    %di, %di
-       subw    %si, %si
-       movw    $0x800, %cx
-       rep
-       movsw
-       cmpw    %bp, %bx                        # assume start_sys_seg > 0x200,
-                                               # so we will perhaps read one
-                                               # page more than needed, but
-                                               # never overwrite INITSEG
-                                               # because destination is a
-                                               # minimum one page below source
-       jb      do_move
-
-end_move:
-# then we load the segment descriptors
-       movw    %cs, %ax                        # aka SETUPSEG
-       movw    %ax, %ds
-               
-# Check whether we need to be downward compatible with version <=201
-       cmpl    $0, cmd_line_ptr
-       jne     end_move_self           # loader uses version >=202 features
-       cmpb    $0x20, type_of_loader
-       je      end_move_self           # bootsect loader, we know of it
-
-# Boot loader doesnt support boot protocol version 2.02.
-# If we have our code not at 0x90000, we need to move it there now.
-# We also then need to move the params behind it (commandline)
-# Because we would overwrite the code on the current IP, we move
-# it in two steps, jumping high after the first one.
-       movw    %cs, %ax
-       cmpw    $SETUPSEG, %ax
-       je      end_move_self
-
-       cli                                     # make sure we really have
-                                               # interrupts disabled !
-                                               # because after this the stack
-                                               # should not be used
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       movw    %ss, %dx
-       cmpw    %ax, %dx
-       jb      move_self_1
-
-       addw    $INITSEG, %dx
-       subw    %ax, %dx                        # this will go into %ss after
-                                               # the move
-move_self_1:
-       movw    %ax, %ds
-       movw    $INITSEG, %ax                   # real INITSEG
-       movw    %ax, %es
-       movw    %cs:setup_move_size, %cx
-       std                                     # we have to move up, so we use
-                                               # direction down because the
-                                               # areas may overlap
-       movw    %cx, %di
-       decw    %di
-       movw    %di, %si
-       subw    $move_self_here+0x200, %cx
-       rep
-       movsb
-       ljmp    $SETUPSEG, $move_self_here
-
-move_self_here:
-       movw    $move_self_here+0x200, %cx
-       rep
-       movsb
-       movw    $SETUPSEG, %ax
-       movw    %ax, %ds
-       movw    %dx, %ss
-end_move_self:                                 # now we are at the right place
-
-#
-# Enable A20.  This is at the very best an annoying procedure.
-# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin.
-# AMD Elan bug fix by Robert Schwebel.
-#
-
-#if defined(CONFIG_X86_ELAN)
-       movb $0x02, %al                 # alternate A20 gate
-       outb %al, $0x92                 # this works on SC410/SC520
-a20_elan_wait:
-       call a20_test
-       jz a20_elan_wait
-       jmp a20_done
-#endif
-
-
-A20_TEST_LOOPS         =  32           # Iterations per wait
-A20_ENABLE_LOOPS       = 255           # Total loops to try            
-
-
-#ifndef CONFIG_X86_VOYAGER
-a20_try_loop:
-
-       # First, see if we are on a system with no A20 gate.
-a20_none:
-       call    a20_test
-       jnz     a20_done
-
-       # Next, try the BIOS (INT 0x15, AX=0x2401)
-a20_bios:
-       movw    $0x2401, %ax
-       pushfl                                  # Be paranoid about flags
-       int     $0x15
-       popfl
-
-       call    a20_test
-       jnz     a20_done
-
-       # Try enabling A20 through the keyboard controller
-#endif /* CONFIG_X86_VOYAGER */
-a20_kbc:
-       call    empty_8042
-
-#ifndef CONFIG_X86_VOYAGER
-       call    a20_test                        # Just in case the BIOS worked
-       jnz     a20_done                        # but had a delayed reaction.
-#endif
-
-       movb    $0xD1, %al                      # command write
-       outb    %al, $0x64
-       call    empty_8042
-
-       movb    $0xDF, %al                      # A20 on
-       outb    %al, $0x60
-       call    empty_8042
-
-#ifndef CONFIG_X86_VOYAGER
-       # Wait until a20 really *is* enabled; it can take a fair amount of
-       # time on certain systems; Toshiba Tecras are known to have this
-       # problem.
-a20_kbc_wait:
-       xorw    %cx, %cx
-a20_kbc_wait_loop:
-       call    a20_test
-       jnz     a20_done
-       loop    a20_kbc_wait_loop
-
-       # Final attempt: use "configuration port A"
-a20_fast:
-       inb     $0x92, %al                      # Configuration Port A
-       orb     $0x02, %al                      # "fast A20" version
-       andb    $0xFE, %al                      # don't accidentally reset
-       outb    %al, $0x92
-
-       # Wait for configuration port A to take effect
-a20_fast_wait:
-       xorw    %cx, %cx
-a20_fast_wait_loop:
-       call    a20_test
-       jnz     a20_done
-       loop    a20_fast_wait_loop
-
-       # A20 is still not responding.  Try frobbing it again.
-       # 
-       decb    (a20_tries)
-       jnz     a20_try_loop
-       
-       movw    $a20_err_msg, %si
-       call    prtstr
-
-a20_die:
-       hlt
-       jmp     a20_die
-
-a20_tries:
-       .byte   A20_ENABLE_LOOPS
-
-a20_err_msg:
-       .ascii  "linux: fatal error: A20 gate not responding!"
-       .byte   13, 10, 0
-
-       # If we get here, all is good
-a20_done:
-
-#endif /* CONFIG_X86_VOYAGER */
-# set up gdt and idt and 32bit start address
-       lidt    idt_48                          # load idt with 0,0
-       xorl    %eax, %eax                      # Compute gdt_base
-       movw    %ds, %ax                        # (Convert %ds:gdt to a linear ptr)
-       shll    $4, %eax
-       addl    %eax, code32
-       addl    $gdt, %eax
-       movl    %eax, (gdt_48+2)
-       lgdt    gdt_48                          # load gdt with whatever is
-                                               # appropriate
-
-# make sure any possible coprocessor is properly reset..
-       xorw    %ax, %ax
-       outb    %al, $0xf0
-       call    delay
-
-       outb    %al, $0xf1
-       call    delay
-
-# well, that went ok, I hope. Now we mask all interrupts - the rest
-# is done in init_IRQ().
-       movb    $0xFF, %al                      # mask all interrupts for now
-       outb    %al, $0xA1
-       call    delay
-       
-       movb    $0xFB, %al                      # mask all irq's but irq2 which
-       outb    %al, $0x21                      # is cascaded
-
-# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
-# need no steenking BIOS anyway (except for the initial loading :-).
-# The BIOS-routine wants lots of unnecessary data, and it's less
-# "interesting" anyway. This is how REAL programmers do it.
-#
-# Well, now's the time to actually move into protected mode. To make
-# things as simple as possible, we do no register set-up or anything,
-# we let the gnu-compiled 32-bit programs do that. We just jump to
-# absolute address 0x1000 (or the loader supplied one),
-# in 32-bit protected mode.
-#
-# Note that the short jump isn't strictly needed, although there are
-# reasons why it might be a good idea. It won't hurt in any case.
-       movw    $1, %ax                         # protected mode (PE) bit
-       lmsw    %ax                             # This is it!
-       jmp     flush_instr
-
-flush_instr:
-       xorw    %bx, %bx                        # Flag to indicate a boot
-       xorl    %esi, %esi                      # Pointer to real-mode code
-       movw    %cs, %si
-       subw    $DELTA_INITSEG, %si
-       shll    $4, %esi                        # Convert to 32-bit pointer
-
-# jump to startup_32 in arch/i386/boot/compressed/head.S
-#      
-# NOTE: For high loaded big kernels we need a
-#      jmpi    0x100000,__BOOT_CS
-#
-#      but we yet haven't reloaded the CS register, so the default size 
-#      of the target offset still is 16 bit.
-#      However, using an operand prefix (0x66), the CPU will properly
-#      take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
-#      Manual, Mixing 16-bit and 32-bit code, page 16-6)
-
-       .byte 0x66, 0xea                        # prefix + jmpi-opcode
-code32:        .long   startup_32                      # will be set to %cs+startup_32
-       .word   __BOOT_CS
-.code32
-startup_32:
-       movl $(__BOOT_DS), %eax
-       movl %eax, %ds
-       movl %eax, %es
-       movl %eax, %fs
-       movl %eax, %gs
-       movl %eax, %ss
-
-       xorl %eax, %eax
-1:     incl %eax                               # check that A20 really IS enabled
-       movl %eax, 0x00000000                   # loop forever if it isn't
-       cmpl %eax, 0x00100000
-       je 1b
-
-       # Jump to the 32bit entry point
-       jmpl *(code32_start - start + (DELTA_INITSEG << 4))(%esi)
-.code16
-
-# Here's a bunch of information about your current kernel..
-kernel_version:        .ascii  UTS_RELEASE
-               .ascii  " ("
-               .ascii  LINUX_COMPILE_BY
-               .ascii  "@"
-               .ascii  LINUX_COMPILE_HOST
-               .ascii  ") "
-               .ascii  UTS_VERSION
-               .byte   0
-
-# This is the default real mode switch routine.
-# to be called just before protected mode transition
-default_switch:
-       cli                                     # no interrupts allowed !
-       movb    $0x80, %al                      # disable NMI for bootup
-                                               # sequence
-       outb    %al, $0x70
-       lret
-
-
-#ifndef CONFIG_X86_VOYAGER
-# This routine tests whether or not A20 is enabled.  If so, it
-# exits with zf = 0.
-#
-# The memory address used, 0x200, is the int $0x80 vector, which
-# should be safe.
-
-A20_TEST_ADDR = 4*0x80
-
-a20_test:
-       pushw   %cx
-       pushw   %ax
-       xorw    %cx, %cx
-       movw    %cx, %fs                        # Low memory
-       decw    %cx
-       movw    %cx, %gs                        # High memory area
-       movw    $A20_TEST_LOOPS, %cx
-       movw    %fs:(A20_TEST_ADDR), %ax
-       pushw   %ax
-a20_test_wait:
-       incw    %ax
-       movw    %ax, %fs:(A20_TEST_ADDR)
-       call    delay                           # Serialize and make delay constant
-       cmpw    %gs:(A20_TEST_ADDR+0x10), %ax
-       loope   a20_test_wait
-
-       popw    %fs:(A20_TEST_ADDR)
-       popw    %ax
-       popw    %cx
-       ret     
-
-#endif /* CONFIG_X86_VOYAGER */
-
-# This routine checks that the keyboard command queue is empty
-# (after emptying the output buffers)
-#
-# Some machines have delusions that the keyboard buffer is always full
-# with no keyboard attached...
-#
-# If there is no keyboard controller, we will usually get 0xff
-# to all the reads.  With each IO taking a microsecond and
-# a timeout of 100,000 iterations, this can take about half a
-# second ("delay" == outb to port 0x80). That should be ok,
-# and should also be plenty of time for a real keyboard controller
-# to empty.
-#
-
-empty_8042:
-       pushl   %ecx
-       movl    $100000, %ecx
-
-empty_8042_loop:
-       decl    %ecx
-       jz      empty_8042_end_loop
-
-       call    delay
-
-       inb     $0x64, %al                      # 8042 status port
-       testb   $1, %al                         # output buffer?
-       jz      no_output
-
-       call    delay
-       inb     $0x60, %al                      # read it
-       jmp     empty_8042_loop
-
-no_output:
-       testb   $2, %al                         # is input buffer full?
-       jnz     empty_8042_loop                 # yes - loop
-empty_8042_end_loop:
-       popl    %ecx
-       ret
-
-# Read the cmos clock. Return the seconds in al
-gettime:
-       pushw   %cx
-       movb    $0x02, %ah
-       int     $0x1a
-       movb    %dh, %al                        # %dh contains the seconds
-       andb    $0x0f, %al
-       movb    %dh, %ah
-       movb    $0x04, %cl
-       shrb    %cl, %ah
-       aad
-       popw    %cx
-       ret
-
-# Delay is needed after doing I/O
-delay:
-       outb    %al,$0x80
-       ret
-
-# Descriptor tables
-#
-# NOTE: The intel manual says gdt should be sixteen bytes aligned for
-# efficiency reasons.  However, there are machines which are known not
-# to boot with misaligned GDTs, so alter this at your peril!  If you alter
-# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
-# empty GDT entries (one for NULL and one reserved).
-#
-# NOTE:        On some CPUs, the GDT must be 8 byte aligned.  This is
-# true for the Voyager Quad CPU card which will not boot without
-# This directive.  16 byte aligment is recommended by intel.
-#
-       .align 16
-gdt:
-       .fill GDT_ENTRY_BOOT_CS,8,0
-
-       .word   0xFFFF                          # 4Gb - (0x100000*0x1000 = 4Gb)
-       .word   0                               # base address = 0
-       .word   0x9A00                          # code read/exec
-       .word   0x00CF                          # granularity = 4096, 386
-                                               #  (+5th nibble of limit)
-
-       .word   0xFFFF                          # 4Gb - (0x100000*0x1000 = 4Gb)
-       .word   0                               # base address = 0
-       .word   0x9200                          # data read/write
-       .word   0x00CF                          # granularity = 4096, 386
-                                               #  (+5th nibble of limit)
-gdt_end:
-       .align  4
-       
-       .word   0                               # alignment byte
-idt_48:
-       .word   0                               # idt limit = 0
-       .word   0, 0                            # idt base = 0L
-
-       .word   0                               # alignment byte
-gdt_48:
-       .word   gdt_end - gdt - 1               # gdt limit
-       .word   0, 0                            # gdt base (filled in later)
-
-# Include video setup & detection code
-
-#include "video.S"
-
-# Setup signature -- must be last
-setup_sig1:    .word   SIG1
-setup_sig2:    .word   SIG2
-
-# After this point, there is some free space which is used by the video mode
-# handling code to store the temporary mode table (not used by the kernel).
-
-modelist:
-
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
diff --git a/arch/i386/boot/setup.ld b/arch/i386/boot/setup.ld
new file mode 100644 (file)
index 0000000..df9234b
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * setup.ld
+ *
+ * Linker script for the i386 setup code
+ */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+       . = 0;
+       .bstext         : { *(.bstext) }
+       .bsdata         : { *(.bsdata) }
+
+       . = 497;
+       .header         : { *(.header) }
+       .inittext       : { *(.inittext) }
+       .initdata       : { *(.initdata) }
+       .text           : { *(.text*) }
+
+       . = ALIGN(16);
+       .rodata         : { *(.rodata*) }
+
+       .videocards     : {
+               video_cards = .;
+               *(.videocards)
+               video_cards_end = .;
+       }
+
+       . = ALIGN(16);
+       .data           : { *(.data*) }
+
+       .signature      : {
+               setup_sig = .;
+               LONG(0x5a5aaa55)
+       }
+
+
+       . = ALIGN(16);
+       .bss            :
+       {
+               __bss_start = .;
+               *(.bss)
+               __bss_end = .;
+       }
+       . = ALIGN(16);
+       _end = .;
+
+       /DISCARD/ : { *(.note*) }
+
+       . = ASSERT(_end <= 0x8000, "Setup too big!");
+       . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!");
+}
diff --git a/arch/i386/boot/string.c b/arch/i386/boot/string.c
new file mode 100644 (file)
index 0000000..481a220
--- /dev/null
@@ -0,0 +1,52 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/string.c
+ *
+ * Very basic string functions
+ */
+
+#include "boot.h"
+
+int strcmp(const char *str1, const char *str2)
+{
+       const unsigned char *s1 = (const unsigned char *)str1;
+       const unsigned char *s2 = (const unsigned char *)str2;
+       int delta = 0;
+
+       while (*s1 || *s2) {
+               delta = *s2 - *s1;
+               if (delta)
+                       return delta;
+               s1++;
+               s2++;
+       }
+       return 0;
+}
+
+size_t strnlen(const char *s, size_t maxlen)
+{
+       const char *es = s;
+       while (*es && maxlen) {
+               es++;
+               maxlen--;
+       }
+
+       return (es - s);
+}
+
+unsigned int atou(const char *s)
+{
+       unsigned int i = 0;
+       while (isdigit(*s))
+               i = i * 10 + (*s++ - '0');
+       return i;
+}
index 05798419a6a93f25be4f347d2eea5e6f04e5ddf6..886f47d8a48883a4c3154ab8ffa3ea77f94f9ad9 100644 (file)
@@ -1,13 +1,12 @@
 /*
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 1997 Martin Mares
+ *  Copyright (C) 2007 H. Peter Anvin
  */
 
 /*
  * This file builds a disk-image from three different files:
  *
- * - bootsect: compatibility mbr which prints an error message if
- *             someone tries to boot the kernel directly.
  * - setup: 8086 machine code, sets up system parm
  * - system: 80386 code for actual system
  *
@@ -21,6 +20,7 @@
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  * Cross compiling fixes by Gertjan van Wingerde, July 1996
  * Rewritten by Martin Mares, April 1997
+ * Substantially overhauled by H. Peter Anvin, April 2007
  */
 
 #include <stdio.h>
 #include <sys/sysmacros.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/mman.h>
 #include <asm/boot.h>
 
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long u32;
+typedef unsigned char  u8;
+typedef unsigned short u16;
+typedef unsigned long  u32;
 
 #define DEFAULT_MAJOR_ROOT 0
 #define DEFAULT_MINOR_ROOT 0
 
-/* Minimal number of setup sectors (see also bootsect.S) */
-#define SETUP_SECTS 4
+/* Minimal number of setup sectors */
+#define SETUP_SECT_MIN 5
+#define SETUP_SECT_MAX 64
 
-byte buf[1024];
-int fd;
+/* This must be large enough to hold the entire setup */
+u8 buf[SETUP_SECT_MAX*512];
 int is_big_kernel;
 
-void die(const char * str, ...)
+static void die(const char * str, ...)
 {
        va_list args;
        va_start(args, str);
@@ -57,15 +59,9 @@ void die(const char * str, ...)
        exit(1);
 }
 
-void file_open(const char *name)
+static void usage(void)
 {
-       if ((fd = open(name, O_RDONLY, 0)) < 0)
-               die("Unable to open `%s': %m", name);
-}
-
-void usage(void)
-{
-       die("Usage: build [-b] bootsect setup system [rootdev] [> image]");
+       die("Usage: build [-b] setup system [rootdev] [> image]");
 }
 
 int main(int argc, char ** argv)
@@ -73,27 +69,30 @@ int main(int argc, char ** argv)
        unsigned int i, sz, setup_sectors;
        int c;
        u32 sys_size;
-       byte major_root, minor_root;
+       u8 major_root, minor_root;
        struct stat sb;
+       FILE *file;
+       int fd;
+       void *kernel;
 
        if (argc > 2 && !strcmp(argv[1], "-b"))
          {
            is_big_kernel = 1;
            argc--, argv++;
          }
-       if ((argc < 4) || (argc > 5))
+       if ((argc < 3) || (argc > 4))
                usage();
-       if (argc > 4) {
-               if (!strcmp(argv[4], "CURRENT")) {
+       if (argc > 3) {
+               if (!strcmp(argv[3], "CURRENT")) {
                        if (stat("/", &sb)) {
                                perror("/");
                                die("Couldn't stat /");
                        }
                        major_root = major(sb.st_dev);
                        minor_root = minor(sb.st_dev);
-               } else if (strcmp(argv[4], "FLOPPY")) {
-                       if (stat(argv[4], &sb)) {
-                               perror(argv[4]);
+               } else if (strcmp(argv[3], "FLOPPY")) {
+                       if (stat(argv[3], &sb)) {
+                               perror(argv[3]);
                                die("Couldn't stat root device.");
                        }
                        major_root = major(sb.st_rdev);
@@ -108,79 +107,62 @@ int main(int argc, char ** argv)
        }
        fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
 
-       file_open(argv[1]);
-       i = read(fd, buf, sizeof(buf));
-       fprintf(stderr,"Boot sector %d bytes.\n",i);
-       if (i != 512)
-               die("Boot block must be exactly 512 bytes");
+       /* Copy the setup code */
+       file = fopen(argv[1], "r");
+       if (!file)
+               die("Unable to open `%s': %m", argv[1]);
+       c = fread(buf, 1, sizeof(buf), file);
+       if (ferror(file))
+               die("read-error on `setup'");
+       if (c < 1024)
+               die("The setup must be at least 1024 bytes");
        if (buf[510] != 0x55 || buf[511] != 0xaa)
                die("Boot block hasn't got boot flag (0xAA55)");
+       fclose(file);
+
+       /* Pad unused space with zeros */
+       setup_sectors = (c + 511) / 512;
+       if (setup_sectors < SETUP_SECT_MIN)
+               setup_sectors = SETUP_SECT_MIN;
+       i = setup_sectors*512;
+       memset(buf+c, 0, i-c);
+
+       /* Set the default root device */
        buf[508] = minor_root;
        buf[509] = major_root;
-       if (write(1, buf, 512) != 512)
-               die("Write call failed");
-       close (fd);
-
-       file_open(argv[2]);                                 /* Copy the setup code */
-       for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c )
-               if (write(1, buf, c) != c)
-                       die("Write call failed");
-       if (c != 0)
-               die("read-error on `setup'");
-       close (fd);
-
-       setup_sectors = (i + 511) / 512;        /* Pad unused space with zeros */
-       /* for compatibility with ancient versions of LILO. */
-       if (setup_sectors < SETUP_SECTS)
-               setup_sectors = SETUP_SECTS;
-       fprintf(stderr, "Setup is %d bytes.\n", i);
-       memset(buf, 0, sizeof(buf));
-       while (i < setup_sectors * 512) {
-               c = setup_sectors * 512 - i;
-               if (c > sizeof(buf))
-                       c = sizeof(buf);
-               if (write(1, buf, c) != c)
-                       die("Write call failed");
-               i += c;
-       }
 
-       file_open(argv[3]);
-       if (fstat (fd, &sb))
-               die("Unable to stat `%s': %m", argv[3]);
+       fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
+
+       /* Open and stat the kernel file */
+       fd = open(argv[2], O_RDONLY);
+       if (fd < 0)
+               die("Unable to open `%s': %m", argv[2]);
+       if (fstat(fd, &sb))
+               die("Unable to stat `%s': %m", argv[2]);
        sz = sb.st_size;
-       fprintf (stderr, "System is %d kB\n", sz/1024);
+       fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
+       kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
+       if (kernel == MAP_FAILED)
+               die("Unable to mmap '%s': %m", argv[2]);
        sys_size = (sz + 15) / 16;
        if (!is_big_kernel && sys_size > DEF_SYSSIZE)
                die("System is too big. Try using bzImage or modules.");
-       while (sz > 0) {
-               int l, n;
-
-               l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
-               if ((n=read(fd, buf, l)) != l) {
-                       if (n < 0)
-                               die("Error reading %s: %m", argv[3]);
-                       else
-                               die("%s: Unexpected EOF", argv[3]);
-               }
-               if (write(1, buf, l) != l)
-                       die("Write failed");
-               sz -= l;
-       }
+
+       /* Patch the setup code with the appropriate size parameters */
+       buf[0x1f1] = setup_sectors-1;
+       buf[0x1f4] = sys_size;
+       buf[0x1f5] = sys_size >> 8;
+       buf[0x1f6] = sys_size >> 16;
+       buf[0x1f7] = sys_size >> 24;
+
+       if (fwrite(buf, 1, i, stdout) != i)
+               die("Writing setup failed");
+
+       /* Copy the kernel code */
+       if (fwrite(kernel, 1, sz, stdout) != sz)
+               die("Writing kernel failed");
        close(fd);
 
-       if (lseek(1, 497, SEEK_SET) != 497)                 /* Write sizes to the bootsector */
-               die("Output: seek failed");
-       buf[0] = setup_sectors;
-       if (write(1, buf, 1) != 1)
-               die("Write of setup sector count failed");
-       if (lseek(1, 500, SEEK_SET) != 500)
-               die("Output: seek failed");
-       buf[0] = (sys_size & 0xff);
-       buf[1] = ((sys_size >> 8) & 0xff);
-       buf[2] = ((sys_size >> 16) & 0xff);
-       buf[3] = ((sys_size >> 24) & 0xff);
-       if (write(1, buf, 4) != 4)
-               die("Write of image length failed");
-
-       return 0;                                           /* Everything is OK */
+       /* Everything is OK */
+       return 0;
 }
diff --git a/arch/i386/boot/tty.c b/arch/i386/boot/tty.c
new file mode 100644 (file)
index 0000000..a8db787
--- /dev/null
@@ -0,0 +1,112 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/tty.c
+ *
+ * Very simple screen I/O
+ * XXX: Probably should add very simple serial I/O?
+ */
+
+#include "boot.h"
+
+/*
+ * These functions are in .inittext so they can be used to signal
+ * error during initialization.
+ */
+
+void __attribute__((section(".inittext"))) putchar(int ch)
+{
+       unsigned char c = ch;
+
+       if (c == '\n')
+               putchar('\r');  /* \n -> \r\n */
+
+       /* int $0x10 is known to have bugs involving touching registers
+          it shouldn't.  Be extra conservative... */
+       asm volatile("pushal; int $0x10; popal"
+                    : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch));
+}
+
+void __attribute__((section(".inittext"))) puts(const char *str)
+{
+       int n = 0;
+       while (*str) {
+               putchar(*str++);
+               n++;
+       }
+}
+
+/*
+ * Read the CMOS clock through the BIOS, and return the
+ * seconds in BCD.
+ */
+
+static u8 gettime(void)
+{
+       u16 ax = 0x0200;
+       u16 cx, dx;
+
+       asm("int $0x1a"
+           : "+a" (ax), "=c" (cx), "=d" (dx)
+           : : "ebx", "esi", "edi");
+
+       return dx >> 8;
+}
+
+/*
+ * Read from the keyboard
+ */
+int getchar(void)
+{
+       u16 ax = 0;
+       asm("int $0x16" : "+a" (ax));
+
+       return ax & 0xff;
+}
+
+static int kbd_pending(void)
+{
+       u8 pending;
+       asm("int $0x16; setnz %0"
+           : "=rm" (pending)
+           : "a" (0x0100));
+       return pending;
+}
+
+void kbd_flush(void)
+{
+       for (;;) {
+               if (!kbd_pending())
+                       break;
+               getchar();
+       }
+}
+
+int getchar_timeout(void)
+{
+       int cnt = 30;
+       int t0, t1;
+
+       t0 = gettime();
+
+       while (cnt) {
+               if (kbd_pending())
+                       return getchar();
+
+               t1 = gettime();
+               if (t0 != t1) {
+                       cnt--;
+                       t0 = t1;
+               }
+       }
+
+       return 0;               /* Timeout! */
+}
diff --git a/arch/i386/boot/version.c b/arch/i386/boot/version.c
new file mode 100644 (file)
index 0000000..c61462f
--- /dev/null
@@ -0,0 +1,23 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/version.c
+ *
+ * Kernel version string
+ */
+
+#include "boot.h"
+#include <linux/utsrelease.h>
+#include <linux/compile.h>
+
+const char kernel_version[] =
+       UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") "
+       UTS_VERSION;
diff --git a/arch/i386/boot/vesa.h b/arch/i386/boot/vesa.h
new file mode 100644 (file)
index 0000000..ff5b73c
--- /dev/null
@@ -0,0 +1,79 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 1999-2007 H. Peter Anvin - 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, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef BOOT_VESA_H
+#define BOOT_VESA_H
+
+typedef struct {
+       u16 off, seg;
+} far_ptr;
+
+/* VESA General Information table */
+struct vesa_general_info {
+       u32 signature;          /* 0 Magic number = "VESA" */
+       u16 version;            /* 4 */
+       far_ptr vendor_string;  /* 6 */
+       u32 capabilities;       /* 10 */
+       far_ptr video_mode_ptr; /* 14 */
+       u16 total_memory;       /* 18 */
+
+       u16 oem_software_rev;   /* 20 */
+       far_ptr oem_vendor_name_ptr;    /* 22 */
+       far_ptr oem_product_name_ptr;   /* 26 */
+       far_ptr oem_product_rev_ptr;    /* 30 */
+
+       u8 reserved[222];       /* 34 */
+       u8 oem_data[256];       /* 256 */
+} __attribute__ ((packed));
+
+#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24))
+#define VBE2_MAGIC ('V' + ('B' << 8) + ('E' << 16) + ('2' << 24))
+
+struct vesa_mode_info {
+       u16 mode_attr;          /* 0 */
+       u8 win_attr[2];         /* 2 */
+       u16 win_grain;          /* 4 */
+       u16 win_size;           /* 6 */
+       u16 win_seg[2];         /* 8 */
+       far_ptr win_scheme;     /* 12 */
+       u16 logical_scan;       /* 16 */
+
+       u16 h_res;              /* 18 */
+       u16 v_res;              /* 20 */
+       u8 char_width;          /* 22 */
+       u8 char_height;         /* 23 */
+       u8 memory_planes;       /* 24 */
+       u8 bpp;                 /* 25 */
+       u8 banks;               /* 26 */
+       u8 memory_layout;       /* 27 */
+       u8 bank_size;           /* 28 */
+       u8 image_planes;        /* 29 */
+       u8 page_function;       /* 30 */
+
+       u8 rmask;               /* 31 */
+       u8 rpos;                /* 32 */
+       u8 gmask;               /* 33 */
+       u8 gpos;                /* 34 */
+       u8 bmask;               /* 35 */
+       u8 bpos;                /* 36 */
+       u8 resv_mask;           /* 37 */
+       u8 resv_pos;            /* 38 */
+       u8 dcm_info;            /* 39 */
+
+       u32 lfb_ptr;            /* 40 Linear frame buffer address */
+       u32 offscreen_ptr;      /* 44 Offscreen memory address */
+       u16 offscreen_size;     /* 48 */
+
+       u8 reserved[206];       /* 50 */
+} __attribute__ ((packed));
+
+#endif                         /* LIB_SYS_VESA_H */
diff --git a/arch/i386/boot/video-bios.c b/arch/i386/boot/video-bios.c
new file mode 100644 (file)
index 0000000..afea46c
--- /dev/null
@@ -0,0 +1,125 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video-bios.c
+ *
+ * Standard video BIOS modes
+ *
+ * We have two options for this; silent and scanned.
+ */
+
+#include "boot.h"
+#include "video.h"
+
+__videocard video_bios;
+
+/* Set a conventional BIOS mode */
+static int set_bios_mode(u8 mode);
+
+static int bios_set_mode(struct mode_info *mi)
+{
+       return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS);
+}
+
+static int set_bios_mode(u8 mode)
+{
+       u16 ax;
+       u8 new_mode;
+
+       ax = mode;              /* AH=0x00 Set Video Mode */
+       asm volatile(INT10
+                    : "+a" (ax)
+                    : : "ebx", "ecx", "edx", "esi", "edi");
+
+       ax = 0x0f00;            /* Get Current Video Mode */
+       asm volatile(INT10
+                    : "+a" (ax)
+                    : : "ebx", "ecx", "edx", "esi", "edi");
+
+       do_restore = 1;         /* Assume video contents was lost */
+       new_mode = ax & 0x7f;   /* Not all BIOSes are clean with the top bit */
+
+       if (new_mode == mode)
+               return 0;       /* Mode change OK */
+
+       if (new_mode != boot_params.screen_info.orig_video_mode) {
+               /* Mode setting failed, but we didn't end up where we
+                  started.  That's bad.  Try to revert to the original
+                  video mode. */
+               ax = boot_params.screen_info.orig_video_mode;
+               asm volatile(INT10
+                            : "+a" (ax)
+                            : : "ebx", "ecx", "edx", "esi", "edi");
+       }
+       return -1;
+}
+
+static int bios_probe(void)
+{
+       u8 mode;
+       u8 saved_mode = boot_params.screen_info.orig_video_mode;
+       u16 crtc;
+       struct mode_info *mi;
+       int nmodes = 0;
+
+       if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA)
+               return 0;
+
+       set_fs(0);
+       crtc = vga_crtc();
+
+       video_bios.modes = GET_HEAP(struct mode_info, 0);
+
+       for (mode = 0x14; mode <= 0x7f; mode++) {
+               if (heap_free() < sizeof(struct mode_info))
+                       break;
+
+               if (mode_defined(VIDEO_FIRST_BIOS+mode))
+                       continue;
+
+               if (set_bios_mode(mode))
+                       continue;
+
+               /* Try to verify that it's a text mode. */
+
+               /* Attribute Controller: make graphics controller disabled */
+               if (in_idx(0x3c0, 0x10) & 0x01)
+                       continue;
+
+               /* Graphics Controller: verify Alpha addressing enabled */
+               if (in_idx(0x3ce, 0x06) & 0x01)
+                       continue;
+
+               /* CRTC cursor location low should be zero(?) */
+               if (in_idx(crtc, 0x0f))
+                       continue;
+
+               mi = GET_HEAP(struct mode_info, 1);
+               mi->mode = VIDEO_FIRST_BIOS+mode;
+               mi->x = rdfs16(0x44a);
+               mi->y = rdfs8(0x484)+1;
+               nmodes++;
+       }
+
+       set_bios_mode(saved_mode);
+
+       return nmodes;
+}
+
+__videocard video_bios =
+{
+       .card_name      = "BIOS (scanned)",
+       .probe          = bios_probe,
+       .set_mode       = bios_set_mode,
+       .unsafe         = 1,
+       .xmode_first    = VIDEO_FIRST_BIOS,
+       .xmode_n        = 0x80,
+};
diff --git a/arch/i386/boot/video-vesa.c b/arch/i386/boot/video-vesa.c
new file mode 100644 (file)
index 0000000..e6aa9eb
--- /dev/null
@@ -0,0 +1,284 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video-vesa.c
+ *
+ * VESA text modes
+ */
+
+#include "boot.h"
+#include "video.h"
+#include "vesa.h"
+
+/* VESA information */
+static struct vesa_general_info vginfo;
+static struct vesa_mode_info vminfo;
+
+__videocard video_vesa;
+
+static void vesa_store_mode_params_graphics(void);
+
+static int vesa_probe(void)
+{
+#if defined(CONFIG_VIDEO_VESA) || defined(CONFIG_FIRMWARE_EDID)
+       u16 ax;
+       u16 mode;
+       addr_t mode_ptr;
+       struct mode_info *mi;
+       int nmodes = 0;
+
+       video_vesa.modes = GET_HEAP(struct mode_info, 0);
+
+       vginfo.signature = VBE2_MAGIC;
+
+       /* Optimistically assume a VESA BIOS is register-clean... */
+       ax = 0x4f00;
+       asm("int $0x10" : "+a" (ax), "=m" (vginfo) : "D" (&vginfo));
+
+       if (ax != 0x004f ||
+           vginfo.signature != VESA_MAGIC ||
+           vginfo.version < 0x0102)
+               return 0;       /* Not present */
+#endif /* CONFIG_VIDEO_VESA || CONFIG_FIRMWARE_EDID */
+#ifdef CONFIG_VIDEO_VESA
+       set_fs(vginfo.video_mode_ptr.seg);
+       mode_ptr = vginfo.video_mode_ptr.off;
+
+       while ((mode = rdfs16(mode_ptr)) != 0xffff) {
+               mode_ptr += 2;
+
+               if (heap_free() < sizeof(struct mode_info))
+                       break;  /* Heap full, can't save mode info */
+
+               if (mode & ~0x1ff)
+                       continue;
+
+               memset(&vminfo, 0, sizeof vminfo); /* Just in case... */
+
+               ax = 0x4f01;
+               asm("int $0x10"
+                   : "+a" (ax), "=m" (vminfo)
+                   : "c" (mode), "D" (&vminfo));
+
+               if (ax != 0x004f)
+                       continue;
+
+               if ((vminfo.mode_attr & 0x15) == 0x05) {
+                       /* Text Mode, TTY BIOS supported,
+                          supported by hardware */
+                       mi = GET_HEAP(struct mode_info, 1);
+                       mi->mode = mode + VIDEO_FIRST_VESA;
+                       mi->x    = vminfo.h_res;
+                       mi->y    = vminfo.v_res;
+                       nmodes++;
+               } else if ((vminfo.mode_attr & 0x99) == 0x99) {
+#ifdef CONFIG_FB
+                       /* Graphics mode, color, linear frame buffer
+                          supported -- register the mode but hide from
+                          the menu.  Only do this if framebuffer is
+                          configured, however, otherwise the user will
+                          be left without a screen. */
+                       mi = GET_HEAP(struct mode_info, 1);
+                       mi->mode = mode + VIDEO_FIRST_VESA;
+                       mi->x = mi->y = 0;
+                       nmodes++;
+#endif
+               }
+       }
+
+       return nmodes;
+#else
+       return 0;
+#endif /* CONFIG_VIDEO_VESA */
+}
+
+static int vesa_set_mode(struct mode_info *mode)
+{
+       u16 ax;
+       int is_graphic;
+       u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA;
+
+       memset(&vminfo, 0, sizeof vminfo); /* Just in case... */
+
+       ax = 0x4f01;
+       asm("int $0x10"
+           : "+a" (ax), "=m" (vminfo)
+           : "c" (vesa_mode), "D" (&vminfo));
+
+       if (ax != 0x004f)
+               return -1;
+
+       if ((vminfo.mode_attr & 0x15) == 0x05) {
+               /* It's a supported text mode */
+               is_graphic = 0;
+       } else if ((vminfo.mode_attr & 0x99) == 0x99) {
+               /* It's a graphics mode with linear frame buffer */
+               is_graphic = 1;
+               vesa_mode |= 0x4000; /* Request linear frame buffer */
+       } else {
+               return -1;      /* Invalid mode */
+       }
+
+
+       ax = 0x4f02;
+       asm volatile("int $0x10"
+                    : "+a" (ax)
+                    : "b" (vesa_mode), "D" (0));
+
+       if (ax != 0x004f)
+               return -1;
+
+       graphic_mode = is_graphic;
+       if (!is_graphic) {
+               /* Text mode */
+               force_x = mode->x;
+               force_y = mode->y;
+               do_restore = 1;
+       } else {
+               /* Graphics mode */
+               vesa_store_mode_params_graphics();
+       }
+
+       return 0;
+}
+
+
+/* Switch DAC to 8-bit mode */
+static void vesa_dac_set_8bits(void)
+{
+       u8 dac_size = 6;
+
+       /* If possible, switch the DAC to 8-bit mode */
+       if (vginfo.capabilities & 1) {
+               u16 ax, bx;
+
+               ax = 0x4f08;
+               bx = 0x0800;
+               asm volatile(INT10
+                            : "+a" (ax), "+b" (bx)
+                            : : "ecx", "edx", "esi", "edi");
+
+               if (ax == 0x004f)
+                       dac_size = bx >> 8;
+       }
+
+       /* Set the color sizes to the DAC size, and offsets to 0 */
+       boot_params.screen_info.red_size = dac_size;
+       boot_params.screen_info.green_size = dac_size;
+       boot_params.screen_info.blue_size = dac_size;
+       boot_params.screen_info.rsvd_size = dac_size;
+
+       boot_params.screen_info.red_pos = 0;
+       boot_params.screen_info.green_pos = 0;
+       boot_params.screen_info.blue_pos = 0;
+       boot_params.screen_info.rsvd_pos = 0;
+}
+
+/* Save the VESA protected mode info */
+static void vesa_store_pm_info(void)
+{
+       u16 ax, bx, di, es;
+
+       ax = 0x4f0a;
+       bx = di = 0;
+       asm("pushw %%es; "INT10"; movw %%es,%0; popw %%es"
+           : "=d" (es), "+a" (ax), "+b" (bx), "+D" (di)
+           : : "ecx", "esi");
+
+       if (ax != 0x004f)
+               return;
+
+       boot_params.screen_info.vesapm_seg = es;
+       boot_params.screen_info.vesapm_off = di;
+}
+
+/*
+ * Save video mode parameters for graphics mode
+ */
+static void vesa_store_mode_params_graphics(void)
+{
+       /* Tell the kernel we're in VESA graphics mode */
+       boot_params.screen_info.orig_video_isVGA = 0x23;
+
+       /* Mode parameters */
+       boot_params.screen_info.vesa_attributes = vminfo.mode_attr;
+       boot_params.screen_info.lfb_linelength = vminfo.logical_scan;
+       boot_params.screen_info.lfb_width = vminfo.h_res;
+       boot_params.screen_info.lfb_height = vminfo.v_res;
+       boot_params.screen_info.lfb_depth = vminfo.bpp;
+       boot_params.screen_info.pages = vminfo.image_planes;
+       boot_params.screen_info.lfb_base = vminfo.lfb_ptr;
+       memcpy(&boot_params.screen_info.red_size,
+              &vminfo.rmask, 8);
+
+       /* General parameters */
+       boot_params.screen_info.lfb_size = vginfo.total_memory;
+
+       if (vminfo.bpp <= 8)
+               vesa_dac_set_8bits();
+
+       vesa_store_pm_info();
+}
+
+/*
+ * Save EDID information for the kernel; this is invoked, separately,
+ * after mode-setting.
+ */
+void vesa_store_edid(void)
+{
+#ifdef CONFIG_FIRMWARE_EDID
+       u16 ax, bx, cx, dx, di;
+
+       /* Apparently used as a nonsense token... */
+       memset(&boot_params.edid_info, 0x13, sizeof boot_params.edid_info);
+
+       if (vginfo.version < 0x0200)
+               return;         /* EDID requires VBE 2.0+ */
+
+       ax = 0x4f15;            /* VBE DDC */
+       bx = 0x0000;            /* Report DDC capabilities */
+       cx = 0;                 /* Controller 0 */
+       di = 0;                 /* ES:DI must be 0 by spec */
+
+       /* Note: The VBE DDC spec is different from the main VESA spec;
+          we genuinely have to assume all registers are destroyed here. */
+
+       asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es"
+           : "+a" (ax), "+b" (bx)
+           :  "c" (cx), "D" (di)
+           : "esi");
+
+       if (ax != 0x004f)
+               return;         /* No EDID */
+
+       /* BH = time in seconds to transfer EDD information */
+       /* BL = DDC level supported */
+
+       ax = 0x4f15;            /* VBE DDC */
+       bx = 0x0001;            /* Read EDID */
+       cx = 0;                 /* Controller 0 */
+       dx = 0;                 /* EDID block number */
+       di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */
+       asm(INT10
+           : "+a" (ax), "+b" (bx), "+d" (dx)
+           : "c" (cx), "D" (di)
+           : "esi");
+#endif /* CONFIG_FIRMWARE_EDID */
+}
+
+__videocard video_vesa =
+{
+       .card_name      = "VESA",
+       .probe          = vesa_probe,
+       .set_mode       = vesa_set_mode,
+       .xmode_first    = VIDEO_FIRST_VESA,
+       .xmode_n        = 0x200,
+};
diff --git a/arch/i386/boot/video-vga.c b/arch/i386/boot/video-vga.c
new file mode 100644 (file)
index 0000000..700d09a
--- /dev/null
@@ -0,0 +1,260 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video-vga.c
+ *
+ * Common all-VGA modes
+ */
+
+#include "boot.h"
+#include "video.h"
+
+static struct mode_info vga_modes[] = {
+       { VIDEO_80x25,  80, 25 },
+       { VIDEO_8POINT, 80, 50 },
+       { VIDEO_80x43,  80, 43 },
+       { VIDEO_80x28,  80, 28 },
+       { VIDEO_80x30,  80, 30 },
+       { VIDEO_80x34,  80, 34 },
+       { VIDEO_80x60,  80, 60 },
+};
+
+static struct mode_info ega_modes[] = {
+       { VIDEO_80x25,  80, 25 },
+       { VIDEO_8POINT, 80, 43 },
+};
+
+static struct mode_info cga_modes[] = {
+       { VIDEO_80x25,  80, 25 },
+};
+
+__videocard video_vga;
+
+/* Set basic 80x25 mode */
+static u8 vga_set_basic_mode(void)
+{
+       u16 ax;
+       u8 rows;
+       u8 mode;
+
+#ifdef CONFIG_VIDEO_400_HACK
+       if (adapter >= ADAPTER_VGA) {
+               asm(INT10
+                   : : "a" (0x1202), "b" (0x0030)
+                   : "ecx", "edx", "esi", "edi");
+       }
+#endif
+
+       ax = 0x0f00;
+       asm(INT10
+           : "+a" (ax)
+           : : "ebx", "ecx", "edx", "esi", "edi");
+
+       mode = (u8)ax;
+
+       set_fs(0);
+       rows = rdfs8(0x484);    /* rows minus one */
+
+#ifndef CONFIG_VIDEO_400_HACK
+       if ((ax == 0x5003 || ax == 0x5007) &&
+           (rows == 0 || rows == 24))
+               return mode;
+#endif
+
+       if (mode != 3 && mode != 7)
+               mode = 3;
+
+       /* Set the mode */
+       asm volatile(INT10
+                    : : "a" (mode)
+                    : "ebx", "ecx", "edx", "esi", "edi");
+       do_restore = 1;
+       return mode;
+}
+
+static void vga_set_8font(void)
+{
+       /* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */
+
+       /* Set 8x8 font */
+       asm volatile(INT10 : : "a" (0x1112), "b" (0));
+
+       /* Use alternate print screen */
+       asm volatile(INT10 : : "a" (0x1200), "b" (0x20));
+
+       /* Turn off cursor emulation */
+       asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
+
+       /* Cursor is scan lines 6-7 */
+       asm volatile(INT10 : : "a" (0x0100), "c" (0x0607));
+}
+
+static void vga_set_14font(void)
+{
+       /* Set 9x14 font - 80x28 on VGA */
+
+       /* Set 9x14 font */
+       asm volatile(INT10 : : "a" (0x1111), "b" (0));
+
+       /* Turn off cursor emulation */
+       asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
+
+       /* Cursor is scan lines 11-12 */
+       asm volatile(INT10 : : "a" (0x0100), "c" (0x0b0c));
+}
+
+static void vga_set_80x43(void)
+{
+       /* Set 80x43 mode on VGA (not EGA) */
+
+       /* Set 350 scans */
+       asm volatile(INT10 : : "a" (0x1201), "b" (0x30));
+
+       /* Reset video mode */
+       asm volatile(INT10 : : "a" (0x0003));
+
+       vga_set_8font();
+}
+
+/* I/O address of the VGA CRTC */
+u16 vga_crtc(void)
+{
+       return (inb(0x3cc) & 1) ? 0x3d4 : 0x3b4;
+}
+
+static void vga_set_480_scanlines(int end)
+{
+       u16 crtc;
+       u8  csel;
+
+       crtc = vga_crtc();
+
+       out_idx(0x0c, crtc, 0x11); /* Vertical sync end, unlock CR0-7 */
+       out_idx(0x0b, crtc, 0x06); /* Vertical total */
+       out_idx(0x3e, crtc, 0x07); /* Vertical overflow */
+       out_idx(0xea, crtc, 0x10); /* Vertical sync start */
+       out_idx(end, crtc, 0x12); /* Vertical display end */
+       out_idx(0xe7, crtc, 0x15); /* Vertical blank start */
+       out_idx(0x04, crtc, 0x16); /* Vertical blank end */
+       csel = inb(0x3cc);
+       csel &= 0x0d;
+       csel |= 0xe2;
+       outb(csel, 0x3cc);
+}
+
+static void vga_set_80x30(void)
+{
+       vga_set_480_scanlines(0xdf);
+}
+
+static void vga_set_80x34(void)
+{
+       vga_set_14font();
+       vga_set_480_scanlines(0xdb);
+}
+
+static void vga_set_80x60(void)
+{
+       vga_set_8font();
+       vga_set_480_scanlines(0xdf);
+}
+
+static int vga_set_mode(struct mode_info *mode)
+{
+       /* Set the basic mode */
+       vga_set_basic_mode();
+
+       /* Override a possibly broken BIOS */
+       force_x = mode->x;
+       force_y = mode->y;
+
+       switch (mode->mode) {
+       case VIDEO_80x25:
+               break;
+       case VIDEO_8POINT:
+               vga_set_8font();
+               break;
+       case VIDEO_80x43:
+               vga_set_80x43();
+               break;
+       case VIDEO_80x28:
+               vga_set_14font();
+               break;
+       case VIDEO_80x30:
+               vga_set_80x30();
+               break;
+       case VIDEO_80x34:
+               vga_set_80x34();
+               break;
+       case VIDEO_80x60:
+               vga_set_80x60();
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * Note: this probe includes basic information required by all
+ * systems.  It should be executed first, by making sure
+ * video-vga.c is listed first in the Makefile.
+ */
+static int vga_probe(void)
+{
+       static const char *card_name[] = {
+               "CGA/MDA/HGC", "EGA", "VGA"
+       };
+       static struct mode_info *mode_lists[] = {
+               cga_modes,
+               ega_modes,
+               vga_modes,
+       };
+       static int mode_count[] = {
+               sizeof(cga_modes)/sizeof(struct mode_info),
+               sizeof(ega_modes)/sizeof(struct mode_info),
+               sizeof(vga_modes)/sizeof(struct mode_info),
+       };
+       u8 vga_flag;
+
+       asm(INT10
+           : "=b" (boot_params.screen_info.orig_video_ega_bx)
+           : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */
+           : "ecx", "edx", "esi", "edi");
+
+       /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
+       if ((u8)boot_params.screen_info.orig_video_ega_bx != 0x10) {
+               /* EGA/VGA */
+               asm(INT10
+                   : "=a" (vga_flag)
+                   : "a" (0x1a00)
+                   : "ebx", "ecx", "edx", "esi", "edi");
+
+               if (vga_flag == 0x1a) {
+                       adapter = ADAPTER_VGA;
+                       boot_params.screen_info.orig_video_isVGA = 1;
+               } else {
+                       adapter = ADAPTER_EGA;
+               }
+       } else {
+               adapter = ADAPTER_CGA;
+       }
+
+       video_vga.modes = mode_lists[adapter];
+       video_vga.card_name = card_name[adapter];
+       return mode_count[adapter];
+}
+
+__videocard video_vga =
+{
+       .card_name      = "VGA",
+       .probe          = vga_probe,
+       .set_mode       = vga_set_mode,
+};
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
deleted file mode 100644 (file)
index 8143c95..0000000
+++ /dev/null
@@ -1,2043 +0,0 @@
-/*     video.S
- *
- *     Display adapter & video mode setup, version 2.13 (14-May-99)
- *
- *     Copyright (C) 1995 -- 1998 Martin Mares <mj@ucw.cz>
- *     Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
- *
- *     Rewritten to use GNU 'as' by Chris Noe <stiker@northlink.com> May 1999
- *
- *     For further information, look at Documentation/svga.txt.
- *
- */
-
-/* Enable autodetection of SVGA adapters and modes. */
-#undef CONFIG_VIDEO_SVGA
-
-/* Enable autodetection of VESA modes */
-#define CONFIG_VIDEO_VESA
-
-/* Enable compacting of mode table */
-#define CONFIG_VIDEO_COMPACT
-
-/* Retain screen contents when switching modes */
-#define CONFIG_VIDEO_RETAIN
-
-/* Enable local mode list */
-#undef CONFIG_VIDEO_LOCAL
-
-/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
-#undef CONFIG_VIDEO_400_HACK
-
-/* Hack that lets you force specific BIOS mode ID and specific dimensions */
-#undef CONFIG_VIDEO_GFX_HACK
-#define VIDEO_GFX_BIOS_AX 0x4f02       /* 800x600 on ThinkPad */
-#define VIDEO_GFX_BIOS_BX 0x0102
-#define VIDEO_GFX_DUMMY_RESOLUTION 0x6425      /* 100x37 */
-
-/* This code uses an extended set of video mode numbers. These include:
- * Aliases for standard modes
- *     NORMAL_VGA (-1)
- *     EXTENDED_VGA (-2)
- *     ASK_VGA (-3)
- * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
- * of compatibility when extending the table. These are between 0x00 and 0xff.
- */
-#define VIDEO_FIRST_MENU 0x0000
-
-/* Standard BIOS video modes (BIOS number + 0x0100) */
-#define VIDEO_FIRST_BIOS 0x0100
-
-/* VESA BIOS video modes (VESA number + 0x0200) */
-#define VIDEO_FIRST_VESA 0x0200
-
-/* Video7 special modes (BIOS number + 0x0900) */
-#define VIDEO_FIRST_V7 0x0900
-
-/* Special video modes */
-#define VIDEO_FIRST_SPECIAL 0x0f00
-#define VIDEO_80x25 0x0f00
-#define VIDEO_8POINT 0x0f01
-#define VIDEO_80x43 0x0f02
-#define VIDEO_80x28 0x0f03
-#define VIDEO_CURRENT_MODE 0x0f04
-#define VIDEO_80x30 0x0f05
-#define VIDEO_80x34 0x0f06
-#define VIDEO_80x60 0x0f07
-#define VIDEO_GFX_HACK 0x0f08
-#define VIDEO_LAST_SPECIAL 0x0f09
-
-/* Video modes given by resolution */
-#define VIDEO_FIRST_RESOLUTION 0x1000
-
-/* The "recalculate timings" flag */
-#define VIDEO_RECALC 0x8000
-
-/* Positions of various video parameters passed to the kernel */
-/* (see also include/linux/tty.h) */
-#define PARAM_CURSOR_POS       0x00
-#define PARAM_VIDEO_PAGE       0x04
-#define PARAM_VIDEO_MODE       0x06
-#define PARAM_VIDEO_COLS       0x07
-#define PARAM_VIDEO_EGA_BX     0x0a
-#define PARAM_VIDEO_LINES      0x0e
-#define PARAM_HAVE_VGA         0x0f
-#define PARAM_FONT_POINTS      0x10
-
-#define PARAM_LFB_WIDTH                0x12
-#define PARAM_LFB_HEIGHT       0x14
-#define PARAM_LFB_DEPTH                0x16
-#define PARAM_LFB_BASE         0x18
-#define PARAM_LFB_SIZE         0x1c
-#define PARAM_LFB_LINELENGTH   0x24
-#define PARAM_LFB_COLORS       0x26
-#define PARAM_VESAPM_SEG       0x2e
-#define PARAM_VESAPM_OFF       0x30
-#define PARAM_LFB_PAGES                0x32
-#define PARAM_VESA_ATTRIB      0x34
-#define PARAM_CAPABILITIES     0x36
-
-/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
-#ifdef CONFIG_VIDEO_RETAIN
-#define DO_STORE call store_screen
-#else
-#define DO_STORE
-#endif /* CONFIG_VIDEO_RETAIN */
-
-# This is the main entry point called by setup.S
-# %ds *must* be pointing to the bootsector
-video: pushw   %ds             # We use different segments
-       pushw   %ds             # FS contains original DS
-       popw    %fs
-       pushw   %cs             # DS is equal to CS
-       popw    %ds
-       pushw   %cs             # ES is equal to CS
-       popw    %es
-       xorw    %ax, %ax
-       movw    %ax, %gs        # GS is zero
-       cld
-       call    basic_detect    # Basic adapter type testing (EGA/VGA/MDA/CGA)
-#ifdef CONFIG_VIDEO_SELECT
-       movw    %fs:(0x01fa), %ax               # User selected video mode
-       cmpw    $ASK_VGA, %ax                   # Bring up the menu
-       jz      vid2
-
-       call    mode_set                        # Set the mode
-       jc      vid1
-
-       leaw    badmdt, %si                     # Invalid mode ID
-       call    prtstr
-vid2:  call    mode_menu
-vid1:
-#ifdef CONFIG_VIDEO_RETAIN
-       call    restore_screen                  # Restore screen contents
-#endif /* CONFIG_VIDEO_RETAIN */
-       call    store_edid
-#endif /* CONFIG_VIDEO_SELECT */
-       call    mode_params                     # Store mode parameters
-       popw    %ds                             # Restore original DS
-       ret
-
-# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
-basic_detect:
-       movb    $0, %fs:(PARAM_HAVE_VGA)
-       movb    $0x12, %ah      # Check EGA/VGA
-       movb    $0x10, %bl
-       int     $0x10
-       movw    %bx, %fs:(PARAM_VIDEO_EGA_BX)   # Identifies EGA to the kernel
-       cmpb    $0x10, %bl                      # No, it's a CGA/MDA/HGA card.
-       je      basret
-
-       incb    adapter
-       movw    $0x1a00, %ax                    # Check EGA or VGA?
-       int     $0x10
-       cmpb    $0x1a, %al                      # 1a means VGA...
-       jne     basret                          # anything else is EGA.
-       
-       incb    %fs:(PARAM_HAVE_VGA)            # We've detected a VGA
-       incb    adapter
-basret:        ret
-
-# Store the video mode parameters for later usage by the kernel.
-# This is done by asking the BIOS except for the rows/columns
-# parameters in the default 80x25 mode -- these are set directly,
-# because some very obscure BIOSes supply insane values.
-mode_params:
-#ifdef CONFIG_VIDEO_SELECT
-       cmpb    $0, graphic_mode
-       jnz     mopar_gr
-#endif
-       movb    $0x03, %ah                      # Read cursor position
-       xorb    %bh, %bh
-       int     $0x10
-       movw    %dx, %fs:(PARAM_CURSOR_POS)
-       movb    $0x0f, %ah                      # Read page/mode/width
-       int     $0x10
-       movw    %bx, %fs:(PARAM_VIDEO_PAGE)
-       movw    %ax, %fs:(PARAM_VIDEO_MODE)     # Video mode and screen width
-       cmpb    $0x7, %al                       # MDA/HGA => segment differs
-       jnz     mopar0
-
-       movw    $0xb000, video_segment
-mopar0: movw   %gs:(0x485), %ax                # Font size
-       movw    %ax, %fs:(PARAM_FONT_POINTS)    # (valid only on EGA/VGA)
-       movw    force_size, %ax                 # Forced size?
-       orw     %ax, %ax
-       jz      mopar1
-
-       movb    %ah, %fs:(PARAM_VIDEO_COLS)
-       movb    %al, %fs:(PARAM_VIDEO_LINES)
-       ret
-
-mopar1:        movb    $25, %al
-       cmpb    $0, adapter                     # If we are on CGA/MDA/HGA, the
-       jz      mopar2                          # screen must have 25 lines.
-
-       movb    %gs:(0x484), %al                # On EGA/VGA, use the EGA+ BIOS
-       incb    %al                             # location of max lines.
-mopar2: movb   %al, %fs:(PARAM_VIDEO_LINES)
-       ret
-
-#ifdef CONFIG_VIDEO_SELECT
-# Fetching of VESA frame buffer parameters
-mopar_gr:
-       leaw    modelist+1024, %di
-       movb    $0x23, %fs:(PARAM_HAVE_VGA)
-       movw    16(%di), %ax
-       movw    %ax, %fs:(PARAM_LFB_LINELENGTH)
-       movw    18(%di), %ax
-       movw    %ax, %fs:(PARAM_LFB_WIDTH)
-       movw    20(%di), %ax
-       movw    %ax, %fs:(PARAM_LFB_HEIGHT)
-       movb    25(%di), %al
-       movb    $0, %ah
-       movw    %ax, %fs:(PARAM_LFB_DEPTH)
-       movb    29(%di), %al    
-       movb    $0, %ah
-       movw    %ax, %fs:(PARAM_LFB_PAGES)
-       movl    40(%di), %eax
-       movl    %eax, %fs:(PARAM_LFB_BASE)
-       movl    31(%di), %eax
-       movl    %eax, %fs:(PARAM_LFB_COLORS)
-       movl    35(%di), %eax
-       movl    %eax, %fs:(PARAM_LFB_COLORS+4)
-       movw    0(%di), %ax
-       movw    %ax, %fs:(PARAM_VESA_ATTRIB)
-
-# get video mem size
-       leaw    modelist+1024, %di
-       movw    $0x4f00, %ax
-       int     $0x10
-       xorl    %eax, %eax
-       movw    18(%di), %ax
-       movl    %eax, %fs:(PARAM_LFB_SIZE)
-
-# store mode capabilities
-       movl 10(%di), %eax
-       movl %eax, %fs:(PARAM_CAPABILITIES)
-
-# switching the DAC to 8-bit is for <= 8 bpp only
-       movw    %fs:(PARAM_LFB_DEPTH), %ax
-       cmpw    $8, %ax
-       jg      dac_done
-
-# get DAC switching capability
-       xorl    %eax, %eax
-       movb    10(%di), %al
-       testb   $1, %al
-       jz      dac_set
-
-# attempt to switch DAC to 8-bit
-       movw    $0x4f08, %ax
-       movw    $0x0800, %bx
-       int     $0x10
-       cmpw    $0x004f, %ax
-       jne     dac_set
-       movb    %bh, dac_size           # store actual DAC size
-
-dac_set:
-# set color size to DAC size
-       movb    dac_size, %al
-       movb    %al, %fs:(PARAM_LFB_COLORS+0)
-       movb    %al, %fs:(PARAM_LFB_COLORS+2)
-       movb    %al, %fs:(PARAM_LFB_COLORS+4)
-       movb    %al, %fs:(PARAM_LFB_COLORS+6)
-
-# set color offsets to 0
-       movb    $0, %fs:(PARAM_LFB_COLORS+1)
-       movb    $0, %fs:(PARAM_LFB_COLORS+3)
-       movb    $0, %fs:(PARAM_LFB_COLORS+5)
-       movb    $0, %fs:(PARAM_LFB_COLORS+7)
-
-dac_done:
-# get protected mode interface informations
-       movw    $0x4f0a, %ax
-       xorw    %bx, %bx
-       xorw    %di, %di
-       int     $0x10
-       cmp     $0x004f, %ax
-       jnz     no_pm
-
-       movw    %es, %fs:(PARAM_VESAPM_SEG)
-       movw    %di, %fs:(PARAM_VESAPM_OFF)
-no_pm: ret
-
-# The video mode menu
-mode_menu:
-       leaw    keymsg, %si                     # "Return/Space/Timeout" message
-       call    prtstr
-       call    flush
-nokey: call    getkt
-
-       cmpb    $0x0d, %al                      # ENTER ?
-       je      listm                           # yes - manual mode selection
-
-       cmpb    $0x20, %al                      # SPACE ?
-       je      defmd1                          # no - repeat
-
-       call    beep
-       jmp     nokey
-
-defmd1:        ret                                     # No mode chosen? Default 80x25
-
-listm: call    mode_table                      # List mode table
-listm0:        leaw    name_bann, %si                  # Print adapter name
-       call    prtstr
-       movw    card_name, %si
-       orw     %si, %si
-       jnz     an2
-
-       movb    adapter, %al
-       leaw    old_name, %si
-       orb     %al, %al
-       jz      an1
-
-       leaw    ega_name, %si
-       decb    %al
-       jz      an1
-
-       leaw    vga_name, %si
-       jmp     an1
-
-an2:   call    prtstr
-       leaw    svga_name, %si
-an1:   call    prtstr
-       leaw    listhdr, %si                    # Table header
-       call    prtstr
-       movb    $0x30, %dl                      # DL holds mode number
-       leaw    modelist, %si
-lm1:   cmpw    $ASK_VGA, (%si)                 # End?
-       jz      lm2
-
-       movb    %dl, %al                        # Menu selection number
-       call    prtchr
-       call    prtsp2
-       lodsw
-       call    prthw                           # Mode ID
-       call    prtsp2
-       movb    0x1(%si), %al
-       call    prtdec                          # Rows
-       movb    $0x78, %al                      # the letter 'x'
-       call    prtchr
-       lodsw
-       call    prtdec                          # Columns
-       movb    $0x0d, %al                      # New line
-       call    prtchr
-       movb    $0x0a, %al
-       call    prtchr
-       incb    %dl                             # Next character
-       cmpb    $0x3a, %dl
-       jnz     lm1
-
-       movb    $0x61, %dl
-       jmp     lm1
-
-lm2:   leaw    prompt, %si                     # Mode prompt
-       call    prtstr
-       leaw    edit_buf, %di                   # Editor buffer
-lm3:   call    getkey
-       cmpb    $0x0d, %al                      # Enter?
-       jz      lment
-
-       cmpb    $0x08, %al                      # Backspace?
-       jz      lmbs
-
-       cmpb    $0x20, %al                      # Printable?
-       jc      lm3
-
-       cmpw    $edit_buf+4, %di                # Enough space?
-       jz      lm3
-
-       stosb
-       call    prtchr
-       jmp     lm3
-
-lmbs:  cmpw    $edit_buf, %di                  # Backspace
-       jz      lm3
-
-       decw    %di
-       movb    $0x08, %al
-       call    prtchr
-       call    prtspc
-       movb    $0x08, %al
-       call    prtchr
-       jmp     lm3
-       
-lment: movb    $0, (%di)
-       leaw    crlft, %si
-       call    prtstr
-       leaw    edit_buf, %si
-       cmpb    $0, (%si)                       # Empty string = default mode
-       jz      lmdef
-
-       cmpb    $0, 1(%si)                      # One character = menu selection
-       jz      mnusel
-
-       cmpw    $0x6373, (%si)                  # "scan" => mode scanning
-       jnz     lmhx
-
-       cmpw    $0x6e61, 2(%si)
-       jz      lmscan
-
-lmhx:  xorw    %bx, %bx                        # Else => mode ID in hex
-lmhex: lodsb
-       orb     %al, %al
-       jz      lmuse1
-
-       subb    $0x30, %al
-       jc      lmbad
-
-       cmpb    $10, %al
-       jc      lmhx1
-
-       subb    $7, %al
-       andb    $0xdf, %al
-       cmpb    $10, %al
-       jc      lmbad
-
-       cmpb    $16, %al
-       jnc     lmbad
-
-lmhx1: shlw    $4, %bx
-       orb     %al, %bl
-       jmp     lmhex
-
-lmuse1:        movw    %bx, %ax
-       jmp     lmuse
-
-mnusel:        lodsb                                   # Menu selection
-       xorb    %ah, %ah
-       subb    $0x30, %al
-       jc      lmbad
-
-       cmpb    $10, %al
-       jc      lmuse
-       
-       cmpb    $0x61-0x30, %al
-       jc      lmbad
-       
-       subb    $0x61-0x30-10, %al
-       cmpb    $36, %al
-       jnc     lmbad
-
-lmuse: call    mode_set
-       jc      lmdef
-
-lmbad: leaw    unknt, %si
-       call    prtstr
-       jmp     lm2
-lmscan:        cmpb    $0, adapter                     # Scanning only on EGA/VGA
-       jz      lmbad
-
-       movw    $0, mt_end                      # Scanning of modes is
-       movb    $1, scanning                    # done as new autodetection.
-       call    mode_table
-       jmp     listm0
-lmdef: ret
-
-# Additional parts of mode_set... (relative jumps, you know)
-setv7:                                         # Video7 extended modes
-       DO_STORE
-       subb    $VIDEO_FIRST_V7>>8, %bh
-       movw    $0x6f05, %ax
-       int     $0x10
-       stc
-       ret
-
-_setrec:       jmp     setrec                  # Ugly...
-_set_80x25:    jmp     set_80x25
-
-# Aliases for backward compatibility.
-setalias:
-       movw    $VIDEO_80x25, %ax
-       incw    %bx
-       jz      mode_set
-
-       movb    $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
-       incw    %bx
-       jnz     setbad                          # Fall-through!
-
-# Setting of user mode (AX=mode ID) => CF=success
-mode_set:
-       movw    %ax, %fs:(0x01fa)               # Store mode for use in acpi_wakeup.S
-       movw    %ax, %bx
-       cmpb    $0xff, %ah
-       jz      setalias
-
-       testb   $VIDEO_RECALC>>8, %ah
-       jnz     _setrec
-
-       cmpb    $VIDEO_FIRST_RESOLUTION>>8, %ah
-       jnc     setres
-       
-       cmpb    $VIDEO_FIRST_SPECIAL>>8, %ah
-       jz      setspc
-       
-       cmpb    $VIDEO_FIRST_V7>>8, %ah
-       jz      setv7
-       
-       cmpb    $VIDEO_FIRST_VESA>>8, %ah
-       jnc     check_vesa
-       
-       orb     %ah, %ah
-       jz      setmenu
-       
-       decb    %ah
-       jz      setbios
-
-setbad:        clc
-       movb    $0, do_restore                  # The screen needn't be restored
-       ret
-
-setvesa:
-       DO_STORE
-       subb    $VIDEO_FIRST_VESA>>8, %bh
-       movw    $0x4f02, %ax                    # VESA BIOS mode set call
-       int     $0x10
-       cmpw    $0x004f, %ax                    # AL=4f if implemented
-       jnz     setbad                          # AH=0 if OK
-
-       stc
-       ret
-
-setbios:
-       DO_STORE
-       int     $0x10                           # Standard BIOS mode set call
-       pushw   %bx
-       movb    $0x0f, %ah                      # Check if really set
-       int     $0x10
-       popw    %bx
-       cmpb    %bl, %al
-       jnz     setbad
-       
-       stc
-       ret
-
-setspc:        xorb    %bh, %bh                        # Set special mode
-       cmpb    $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
-       jnc     setbad
-       
-       addw    %bx, %bx
-       jmp     *spec_inits(%bx)
-
-setmenu:
-       orb     %al, %al                        # 80x25 is an exception
-       jz      _set_80x25
-       
-       pushw   %bx                             # Set mode chosen from menu
-       call    mode_table                      # Build the mode table
-       popw    %ax
-       shlw    $2, %ax
-       addw    %ax, %si
-       cmpw    %di, %si
-       jnc     setbad
-       
-       movw    (%si), %ax                      # Fetch mode ID
-_m_s:  jmp     mode_set
-
-setres:        pushw   %bx                             # Set mode chosen by resolution
-       call    mode_table
-       popw    %bx
-       xchgb   %bl, %bh
-setr1: lodsw
-       cmpw    $ASK_VGA, %ax                   # End of the list?
-       jz      setbad
-       
-       lodsw
-       cmpw    %bx, %ax
-       jnz     setr1
-       
-       movw    -4(%si), %ax                    # Fetch mode ID
-       jmp     _m_s
-
-check_vesa:
-#ifdef CONFIG_FIRMWARE_EDID
-       leaw    modelist+1024, %di
-       movw    $0x4f00, %ax
-       int     $0x10
-       cmpw    $0x004f, %ax
-       jnz     setbad
-
-       movw    4(%di), %ax
-       movw    %ax, vbe_version
-#endif
-       leaw    modelist+1024, %di
-       subb    $VIDEO_FIRST_VESA>>8, %bh
-       movw    %bx, %cx                        # Get mode information structure
-       movw    $0x4f01, %ax
-       int     $0x10
-       addb    $VIDEO_FIRST_VESA>>8, %bh
-       cmpw    $0x004f, %ax
-       jnz     setbad
-
-       movb    (%di), %al                      # Check capabilities.
-       andb    $0x19, %al
-       cmpb    $0x09, %al
-       jz      setvesa                         # This is a text mode
-
-       movb    (%di), %al                      # Check capabilities.
-       andb    $0x99, %al
-       cmpb    $0x99, %al
-       jnz     _setbad                         # Doh! No linear frame buffer.
-
-       subb    $VIDEO_FIRST_VESA>>8, %bh
-       orw     $0x4000, %bx                    # Use linear frame buffer
-       movw    $0x4f02, %ax                    # VESA BIOS mode set call
-       int     $0x10
-       cmpw    $0x004f, %ax                    # AL=4f if implemented
-       jnz     _setbad                         # AH=0 if OK
-
-       movb    $1, graphic_mode                # flag graphic mode
-       movb    $0, do_restore                  # no screen restore
-       stc
-       ret
-
-_setbad:       jmp     setbad                  # Ugly...
-
-# Recalculate vertical display end registers -- this fixes various
-# inconsistencies of extended modes on many adapters. Called when
-# the VIDEO_RECALC flag is set in the mode ID.
-
-setrec:        subb    $VIDEO_RECALC>>8, %ah           # Set the base mode
-       call    mode_set
-       jnc     rct3
-
-       movw    %gs:(0x485), %ax                # Font size in pixels
-       movb    %gs:(0x484), %bl                # Number of rows
-       incb    %bl
-       mulb    %bl                             # Number of visible
-       decw    %ax                             # scan lines - 1
-       movw    $0x3d4, %dx
-       movw    %ax, %bx
-       movb    $0x12, %al                      # Lower 8 bits
-       movb    %bl, %ah
-       outw    %ax, %dx
-       movb    $0x07, %al              # Bits 8 and 9 in the overflow register
-       call    inidx
-       xchgb   %al, %ah
-       andb    $0xbd, %ah
-       shrb    %bh
-       jnc     rct1
-       orb     $0x02, %ah
-rct1:  shrb    %bh
-       jnc     rct2
-       orb     $0x40, %ah
-rct2:  movb    $0x07, %al
-       outw    %ax, %dx
-       stc
-rct3:  ret
-
-# Table of routines for setting of the special modes.
-spec_inits:
-       .word   set_80x25
-       .word   set_8pixel
-       .word   set_80x43
-       .word   set_80x28
-       .word   set_current
-       .word   set_80x30
-       .word   set_80x34
-       .word   set_80x60
-       .word   set_gfx
-
-# Set the 80x25 mode. If already set, do nothing.
-set_80x25:
-       movw    $0x5019, force_size             # Override possibly broken BIOS
-use_80x25:
-#ifdef CONFIG_VIDEO_400_HACK
-       movw    $0x1202, %ax                    # Force 400 scan lines
-       movb    $0x30, %bl
-       int     $0x10
-#else
-       movb    $0x0f, %ah                      # Get current mode ID
-       int     $0x10
-       cmpw    $0x5007, %ax    # Mode 7 (80x25 mono) is the only one available
-       jz      st80            # on CGA/MDA/HGA and is also available on EGAM
-
-       cmpw    $0x5003, %ax    # Unknown mode, force 80x25 color
-       jnz     force3
-
-st80:  cmpb    $0, adapter     # CGA/MDA/HGA => mode 3/7 is always 80x25
-       jz      set80
-
-       movb    %gs:(0x0484), %al       # This is EGA+ -- beware of 80x50 etc.
-       orb     %al, %al                # Some buggy BIOS'es set 0 rows
-       jz      set80
-       
-       cmpb    $24, %al                # It's hopefully correct
-       jz      set80
-#endif /* CONFIG_VIDEO_400_HACK */
-force3:        DO_STORE
-       movw    $0x0003, %ax                    # Forced set
-       int     $0x10
-set80: stc
-       ret
-
-# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
-set_8pixel:
-       DO_STORE
-       call    use_80x25                       # The base is 80x25
-set_8pt:
-       movw    $0x1112, %ax                    # Use 8x8 font
-       xorb    %bl, %bl
-       int     $0x10
-       movw    $0x1200, %ax                    # Use alternate print screen
-       movb    $0x20, %bl
-       int     $0x10
-       movw    $0x1201, %ax                    # Turn off cursor emulation
-       movb    $0x34, %bl
-       int     $0x10
-       movb    $0x01, %ah                      # Define cursor scan lines 6-7
-       movw    $0x0607, %cx
-       int     $0x10
-set_current:
-       stc
-       ret
-
-# Set the 80x28 mode. This mode works on all VGA's, because it's a standard
-# 80x25 mode with 14-point fonts instead of 16-point.
-set_80x28:
-       DO_STORE
-       call    use_80x25                       # The base is 80x25
-set14: movw    $0x1111, %ax                    # Use 9x14 font
-       xorb    %bl, %bl
-       int     $0x10
-       movb    $0x01, %ah                      # Define cursor scan lines 11-12
-       movw    $0x0b0c, %cx
-       int     $0x10
-       stc
-       ret
-
-# Set the 80x43 mode. This mode is works on all VGA's.
-# It's a 350-scanline mode with 8-pixel font.
-set_80x43:
-       DO_STORE
-       movw    $0x1201, %ax                    # Set 350 scans
-       movb    $0x30, %bl
-       int     $0x10
-       movw    $0x0003, %ax                    # Reset video mode
-       int     $0x10
-       jmp     set_8pt                         # Use 8-pixel font
-
-# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
-set_80x30:
-       call    use_80x25                       # Start with real 80x25
-       DO_STORE
-       movw    $0x3cc, %dx                     # Get CRTC port
-       inb     %dx, %al
-       movb    $0xd4, %dl
-       rorb    %al                             # Mono or color?
-       jc      set48a
-
-       movb    $0xb4, %dl
-set48a:        movw    $0x0c11, %ax            # Vertical sync end (also unlocks CR0-7)
-       call    outidx
-       movw    $0x0b06, %ax                    # Vertical total
-       call    outidx
-       movw    $0x3e07, %ax                    # (Vertical) overflow
-       call    outidx
-       movw    $0xea10, %ax                    # Vertical sync start
-       call    outidx
-       movw    $0xdf12, %ax                    # Vertical display end
-       call    outidx
-       movw    $0xe715, %ax                    # Vertical blank start
-       call    outidx
-       movw    $0x0416, %ax                    # Vertical blank end
-       call    outidx
-       pushw   %dx
-       movb    $0xcc, %dl                      # Misc output register (read)
-       inb     %dx, %al
-       movb    $0xc2, %dl                      # (write)
-       andb    $0x0d, %al      # Preserve clock select bits and color bit
-       orb     $0xe2, %al                      # Set correct sync polarity
-       outb    %al, %dx
-       popw    %dx
-       movw    $0x501e, force_size
-       stc                                     # That's all.
-       ret
-
-# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
-set_80x34:
-       call    set_80x30                       # Set 480 scans
-       call    set14                           # And 14-pt font
-       movw    $0xdb12, %ax                    # VGA vertical display end
-       movw    $0x5022, force_size
-setvde:        call    outidx
-       stc
-       ret
-
-# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
-set_80x60:
-       call    set_80x30                       # Set 480 scans
-       call    set_8pt                         # And 8-pt font
-       movw    $0xdf12, %ax                    # VGA vertical display end
-       movw    $0x503c, force_size
-       jmp     setvde
-
-# Special hack for ThinkPad graphics
-set_gfx:
-#ifdef CONFIG_VIDEO_GFX_HACK
-       movw    $VIDEO_GFX_BIOS_AX, %ax
-       movw    $VIDEO_GFX_BIOS_BX, %bx
-       int     $0x10
-       movw    $VIDEO_GFX_DUMMY_RESOLUTION, force_size
-       stc
-#endif
-       ret
-
-#ifdef CONFIG_VIDEO_RETAIN
-
-# Store screen contents to temporary buffer.
-store_screen:
-       cmpb    $0, do_restore                  # Already stored?
-       jnz     stsr
-
-       testb   $CAN_USE_HEAP, loadflags        # Have we space for storing?
-       jz      stsr
-       
-       pushw   %ax
-       pushw   %bx
-       pushw   force_size                      # Don't force specific size
-       movw    $0, force_size
-       call    mode_params                     # Obtain params of current mode
-       popw    force_size
-       movb    %fs:(PARAM_VIDEO_LINES), %ah
-       movb    %fs:(PARAM_VIDEO_COLS), %al
-       movw    %ax, %bx                        # BX=dimensions
-       mulb    %ah
-       movw    %ax, %cx                        # CX=number of characters
-       addw    %ax, %ax                        # Calculate image size
-       addw    $modelist+1024+4, %ax
-       cmpw    heap_end_ptr, %ax
-       jnc     sts1                            # Unfortunately, out of memory
-
-       movw    %fs:(PARAM_CURSOR_POS), %ax     # Store mode params
-       leaw    modelist+1024, %di
-       stosw
-       movw    %bx, %ax
-       stosw
-       pushw   %ds                             # Store the screen
-       movw    video_segment, %ds
-       xorw    %si, %si
-       rep
-       movsw
-       popw    %ds
-       incb    do_restore                      # Screen will be restored later
-sts1:  popw    %bx
-       popw    %ax
-stsr:  ret
-
-# Restore screen contents from temporary buffer.
-restore_screen:
-       cmpb    $0, do_restore                  # Has the screen been stored?
-       jz      res1
-
-       call    mode_params                     # Get parameters of current mode
-       movb    %fs:(PARAM_VIDEO_LINES), %cl
-       movb    %fs:(PARAM_VIDEO_COLS), %ch
-       leaw    modelist+1024, %si              # Screen buffer
-       lodsw                                   # Set cursor position
-       movw    %ax, %dx
-       cmpb    %cl, %dh
-       jc      res2
-       
-       movb    %cl, %dh
-       decb    %dh
-res2:  cmpb    %ch, %dl
-       jc      res3
-       
-       movb    %ch, %dl
-       decb    %dl
-res3:  movb    $0x02, %ah
-       movb    $0x00, %bh
-       int     $0x10
-       lodsw                                   # Display size
-       movb    %ah, %dl                        # DL=number of lines
-       movb    $0, %ah                         # BX=phys. length of orig. line
-       movw    %ax, %bx
-       cmpb    %cl, %dl                        # Too many?
-       jc      res4
-
-       pushw   %ax
-       movb    %dl, %al
-       subb    %cl, %al
-       mulb    %bl
-       addw    %ax, %si
-       addw    %ax, %si
-       popw    %ax
-       movb    %cl, %dl
-res4:  cmpb    %ch, %al                        # Too wide?
-       jc      res5
-       
-       movb    %ch, %al                        # AX=width of src. line
-res5:  movb    $0, %cl
-       xchgb   %ch, %cl
-       movw    %cx, %bp                        # BP=width of dest. line
-       pushw   %es
-       movw    video_segment, %es
-       xorw    %di, %di                        # Move the data
-       addw    %bx, %bx                        # Convert BX and BP to _bytes_
-       addw    %bp, %bp
-res6:  pushw   %si
-       pushw   %di
-       movw    %ax, %cx
-       rep
-       movsw
-       popw    %di
-       popw    %si
-       addw    %bp, %di
-       addw    %bx, %si
-       decb    %dl
-       jnz     res6
-       
-       popw    %es                             # Done
-res1:  ret
-#endif /* CONFIG_VIDEO_RETAIN */
-
-# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
-outidx:        outb    %al, %dx
-       pushw   %ax
-       movb    %ah, %al
-       incw    %dx
-       outb    %al, %dx
-       decw    %dx
-       popw    %ax
-       ret
-
-# Build the table of video modes (stored after the setup.S code at the
-# `modelist' label. Each video mode record looks like:
-#      .word   MODE-ID         (our special mode ID (see above))
-#      .byte   rows            (number of rows)
-#      .byte   columns         (number of columns)
-# Returns address of the end of the table in DI, the end is marked
-# with a ASK_VGA ID.
-mode_table:
-       movw    mt_end, %di                     # Already filled?
-       orw     %di, %di
-       jnz     mtab1x
-       
-       leaw    modelist, %di                   # Store standard modes:
-       movl    $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
-       stosl
-       movb    adapter, %al                    # CGA/MDA/HGA -- no more modes
-       orb     %al, %al
-       jz      mtabe
-       
-       decb    %al
-       jnz     mtabv
-       
-       movl    $VIDEO_8POINT + 0x502b0000, %eax        # The 80x43 EGA mode
-       stosl
-       jmp     mtabe
-
-mtab1x:        jmp     mtab1
-
-mtabv: leaw    vga_modes, %si                  # All modes for std VGA
-       movw    $vga_modes_end-vga_modes, %cx
-       rep     # I'm unable to use movsw as I don't know how to store a half
-       movsb   # of the expression above to cx without using explicit shr.
-
-       cmpb    $0, scanning                    # Mode scan requested?
-       jz      mscan1
-       
-       call    mode_scan
-mscan1:
-
-#ifdef CONFIG_VIDEO_LOCAL
-       call    local_modes
-#endif /* CONFIG_VIDEO_LOCAL */
-
-#ifdef CONFIG_VIDEO_VESA
-       call    vesa_modes                      # Detect VESA VGA modes
-#endif /* CONFIG_VIDEO_VESA */
-
-#ifdef CONFIG_VIDEO_SVGA
-       cmpb    $0, scanning                    # Bypass when scanning
-       jnz     mscan2
-       
-       call    svga_modes                      # Detect SVGA cards & modes
-mscan2:
-#endif /* CONFIG_VIDEO_SVGA */
-
-mtabe:
-
-#ifdef CONFIG_VIDEO_COMPACT
-       leaw    modelist, %si
-       movw    %di, %dx
-       movw    %si, %di
-cmt1:  cmpw    %dx, %si                        # Scan all modes
-       jz      cmt2
-
-       leaw    modelist, %bx                   # Find in previous entries
-       movw    2(%si), %cx
-cmt3:  cmpw    %bx, %si
-       jz      cmt4
-
-       cmpw    2(%bx), %cx                     # Found => don't copy this entry
-       jz      cmt5
-
-       addw    $4, %bx
-       jmp     cmt3
-
-cmt4:  movsl                                   # Copy entry
-       jmp     cmt1
-
-cmt5:  addw    $4, %si                         # Skip entry
-       jmp     cmt1
-
-cmt2:
-#endif /* CONFIG_VIDEO_COMPACT */
-
-       movw    $ASK_VGA, (%di)                 # End marker
-       movw    %di, mt_end
-mtab1: leaw    modelist, %si                   # SI=mode list, DI=list end
-ret0:  ret
-
-# Modes usable on all standard VGAs
-vga_modes:
-       .word   VIDEO_8POINT
-       .word   0x5032                          # 80x50
-       .word   VIDEO_80x43
-       .word   0x502b                          # 80x43
-       .word   VIDEO_80x28
-       .word   0x501c                          # 80x28
-       .word   VIDEO_80x30
-       .word   0x501e                          # 80x30
-       .word   VIDEO_80x34
-       .word   0x5022                          # 80x34
-       .word   VIDEO_80x60
-       .word   0x503c                          # 80x60
-#ifdef CONFIG_VIDEO_GFX_HACK
-       .word   VIDEO_GFX_HACK
-       .word   VIDEO_GFX_DUMMY_RESOLUTION
-#endif
-
-vga_modes_end:
-# Detect VESA modes.
-
-#ifdef CONFIG_VIDEO_VESA
-vesa_modes:
-       cmpb    $2, adapter                     # VGA only
-       jnz     ret0
-
-       movw    %di, %bp                        # BP=original mode table end
-       addw    $0x200, %di                     # Buffer space
-       movw    $0x4f00, %ax                    # VESA Get card info call
-       int     $0x10
-       movw    %bp, %di
-       cmpw    $0x004f, %ax                    # Successful?
-       jnz     ret0
-       
-       cmpw    $0x4556, 0x200(%di)
-       jnz     ret0
-       
-       cmpw    $0x4153, 0x202(%di)
-       jnz     ret0
-       
-       movw    $vesa_name, card_name           # Set name to "VESA VGA"
-       pushw   %gs
-       lgsw    0x20e(%di), %si                 # GS:SI=mode list
-       movw    $128, %cx                       # Iteration limit
-vesa1:
-# gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
-# XXX: lodsw   %gs:(%si), %ax                  # Get next mode in the list
-       gs; lodsw
-       cmpw    $0xffff, %ax                    # End of the table?
-       jz      vesar
-       
-       cmpw    $0x0080, %ax                    # Check validity of mode ID
-       jc      vesa2
-       
-       orb     %ah, %ah                # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
-       jz      vesan                   # Certain BIOSes report 0x80-0xff!
-
-       cmpw    $0x0800, %ax
-       jnc     vesae
-
-vesa2: pushw   %cx
-       movw    %ax, %cx                        # Get mode information structure
-       movw    $0x4f01, %ax
-       int     $0x10
-       movw    %cx, %bx                        # BX=mode number
-       addb    $VIDEO_FIRST_VESA>>8, %bh
-       popw    %cx
-       cmpw    $0x004f, %ax
-       jnz     vesan                   # Don't report errors (buggy BIOSES)
-
-       movb    (%di), %al                      # Check capabilities. We require
-       andb    $0x19, %al                      # a color text mode.
-       cmpb    $0x09, %al
-       jnz     vesan
-       
-       cmpw    $0xb800, 8(%di)         # Standard video memory address required
-       jnz     vesan
-
-       testb   $2, (%di)                       # Mode characteristics supplied?
-       movw    %bx, (%di)                      # Store mode number
-       jz      vesa3
-       
-       xorw    %dx, %dx
-       movw    0x12(%di), %bx                  # Width
-       orb     %bh, %bh
-       jnz     vesan
-       
-       movb    %bl, 0x3(%di)
-       movw    0x14(%di), %ax                  # Height
-       orb     %ah, %ah
-       jnz     vesan
-       
-       movb    %al, 2(%di)
-       mulb    %bl
-       cmpw    $8193, %ax              # Small enough for Linux console driver?
-       jnc     vesan
-
-       jmp     vesaok
-
-vesa3: subw    $0x8108, %bx    # This mode has no detailed info specified,
-       jc      vesan           # so it must be a standard VESA mode.
-
-       cmpw    $5, %bx
-       jnc     vesan
-
-       movw    vesa_text_mode_table(%bx), %ax
-       movw    %ax, 2(%di)
-vesaok:        addw    $4, %di                         # The mode is valid. Store it.
-vesan: loop    vesa1                   # Next mode. Limit exceeded => error
-vesae: leaw    vesaer, %si
-       call    prtstr
-       movw    %bp, %di                        # Discard already found modes.
-vesar: popw    %gs
-       ret
-
-# Dimensions of standard VESA text modes
-vesa_text_mode_table:
-       .byte   60, 80                          # 0108
-       .byte   25, 132                         # 0109
-       .byte   43, 132                         # 010A
-       .byte   50, 132                         # 010B
-       .byte   60, 132                         # 010C
-#endif /* CONFIG_VIDEO_VESA */
-
-# Scan for video modes. A bit dirty, but should work.
-mode_scan:
-       movw    $0x0100, %cx                    # Start with mode 0
-scm1:  movb    $0, %ah                         # Test the mode
-       movb    %cl, %al
-       int     $0x10
-       movb    $0x0f, %ah
-       int     $0x10
-       cmpb    %cl, %al
-       jnz     scm2                            # Mode not set
-
-       movw    $0x3c0, %dx                     # Test if it's a text mode
-       movb    $0x10, %al                      # Mode bits
-       call    inidx
-       andb    $0x03, %al
-       jnz     scm2
-       
-       movb    $0xce, %dl                      # Another set of mode bits
-       movb    $0x06, %al
-       call    inidx
-       shrb    %al
-       jc      scm2
-       
-       movb    $0xd4, %dl                      # Cursor location
-       movb    $0x0f, %al
-       call    inidx
-       orb     %al, %al
-       jnz     scm2
-       
-       movw    %cx, %ax                        # Ok, store the mode
-       stosw
-       movb    %gs:(0x484), %al                # Number of rows
-       incb    %al
-       stosb
-       movw    %gs:(0x44a), %ax                # Number of columns
-       stosb
-scm2:  incb    %cl
-       jns     scm1
-       
-       movw    $0x0003, %ax                    # Return back to mode 3
-       int     $0x10
-       ret
-
-tstidx:        outw    %ax, %dx                        # OUT DX,AX and inidx
-inidx: outb    %al, %dx                        # Read from indexed VGA register
-       incw    %dx                     # AL=index, DX=index reg port -> AL=data
-       inb     %dx, %al
-       decw    %dx
-       ret
-
-# Try to detect type of SVGA card and supply (usually approximate) video
-# mode table for it.
-
-#ifdef CONFIG_VIDEO_SVGA
-svga_modes:
-       leaw    svga_table, %si                 # Test all known SVGA adapters
-dosvga:        lodsw
-       movw    %ax, %bp                        # Default mode table
-       orw     %ax, %ax
-       jz      didsv1
-
-       lodsw                                   # Pointer to test routine
-       pushw   %si
-       pushw   %di
-       pushw   %es
-       movw    $0xc000, %bx
-       movw    %bx, %es
-       call    *%ax                            # Call test routine
-       popw    %es
-       popw    %di
-       popw    %si
-       orw     %bp, %bp
-       jz      dosvga
-       
-       movw    %bp, %si                        # Found, copy the modes
-       movb    svga_prefix, %ah
-cpsvga:        lodsb
-       orb     %al, %al
-       jz      didsv
-       
-       stosw
-       movsw
-       jmp     cpsvga
-
-didsv: movw    %si, card_name                  # Store pointer to card name
-didsv1:        ret
-
-# Table of all known SVGA cards. For each card, we store a pointer to
-# a table of video modes supported by the card and a pointer to a routine
-# used for testing of presence of the card. The video mode table is always
-# followed by the name of the card or the chipset.
-svga_table:
-       .word   ati_md, ati_test
-       .word   oak_md, oak_test
-       .word   paradise_md, paradise_test
-       .word   realtek_md, realtek_test
-       .word   s3_md, s3_test
-       .word   chips_md, chips_test
-       .word   video7_md, video7_test
-       .word   cirrus5_md, cirrus5_test
-       .word   cirrus6_md, cirrus6_test
-       .word   cirrus1_md, cirrus1_test
-       .word   ahead_md, ahead_test
-       .word   everex_md, everex_test
-       .word   genoa_md, genoa_test
-       .word   trident_md, trident_test
-       .word   tseng_md, tseng_test
-       .word   0
-
-# Test routines and mode tables:
-
-# S3 - The test algorithm was taken from the SuperProbe package
-# for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
-s3_test:
-       movw    $0x0f35, %cx    # we store some constants in cl/ch
-       movw    $0x03d4, %dx
-       movb    $0x38, %al
-       call    inidx
-       movb    %al, %bh        # store current CRT-register 0x38
-       movw    $0x0038, %ax
-       call    outidx          # disable writing to special regs
-       movb    %cl, %al        # check whether we can write special reg 0x35
-       call    inidx
-       movb    %al, %bl        # save the current value of CRT reg 0x35
-       andb    $0xf0, %al      # clear bits 0-3
-       movb    %al, %ah
-       movb    %cl, %al        # and write it to CRT reg 0x35
-       call    outidx
-       call    inidx           # now read it back
-       andb    %ch, %al        # clear the upper 4 bits
-       jz      s3_2            # the first test failed. But we have a
-
-       movb    %bl, %ah        # second chance
-       movb    %cl, %al
-       call    outidx
-       jmp     s3_1            # do the other tests
-
-s3_2:  movw    %cx, %ax        # load ah with 0xf and al with 0x35
-       orb     %bl, %ah        # set the upper 4 bits of ah with the orig value
-       call    outidx          # write ...
-       call    inidx           # ... and reread 
-       andb    %cl, %al        # turn off the upper 4 bits
-       pushw   %ax
-       movb    %bl, %ah        # restore old value in register 0x35
-       movb    %cl, %al
-       call    outidx
-       popw    %ax
-       cmpb    %ch, %al        # setting lower 4 bits was successful => bad
-       je      no_s3           # writing is allowed => this is not an S3
-
-s3_1:  movw    $0x4838, %ax    # allow writing to special regs by putting
-       call    outidx          # magic number into CRT-register 0x38
-       movb    %cl, %al        # check whether we can write special reg 0x35
-       call    inidx
-       movb    %al, %bl
-       andb    $0xf0, %al
-       movb    %al, %ah
-       movb    %cl, %al
-       call    outidx
-       call    inidx
-       andb    %ch, %al
-       jnz     no_s3           # no, we can't write => no S3
-
-       movw    %cx, %ax
-       orb     %bl, %ah
-       call    outidx
-       call    inidx
-       andb    %ch, %al
-       pushw   %ax
-       movb    %bl, %ah        # restore old value in register 0x35
-       movb    %cl, %al
-       call    outidx
-       popw    %ax
-       cmpb    %ch, %al
-       jne     no_s31          # writing not possible => no S3
-       movb    $0x30, %al
-       call    inidx           # now get the S3 id ...
-       leaw    idS3, %di
-       movw    $0x10, %cx
-       repne
-       scasb
-       je      no_s31
-
-       movb    %bh, %ah
-       movb    $0x38, %al
-       jmp     s3rest
-
-no_s3: movb    $0x35, %al      # restore CRT register 0x35
-       movb    %bl, %ah
-       call    outidx
-no_s31:        xorw    %bp, %bp        # Detection failed
-s3rest:        movb    %bh, %ah
-       movb    $0x38, %al      # restore old value of CRT register 0x38
-       jmp     outidx
-
-idS3:  .byte   0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
-       .byte   0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
-
-s3_md: .byte   0x54, 0x2b, 0x84
-       .byte   0x55, 0x19, 0x84
-       .byte   0
-       .ascii  "S3"
-       .byte   0
-
-# ATI cards.
-ati_test:
-       leaw    idati, %si
-       movw    $0x31, %di
-       movw    $0x09, %cx
-       repe
-       cmpsb
-       je      atiok
-
-       xorw    %bp, %bp
-atiok: ret
-
-idati: .ascii  "761295520"
-
-ati_md:        .byte   0x23, 0x19, 0x84
-       .byte   0x33, 0x2c, 0x84
-       .byte   0x22, 0x1e, 0x64
-       .byte   0x21, 0x19, 0x64
-       .byte   0x58, 0x21, 0x50
-       .byte   0x5b, 0x1e, 0x50
-       .byte   0
-       .ascii  "ATI"
-       .byte   0
-
-# AHEAD
-ahead_test:
-       movw    $0x200f, %ax
-       movw    $0x3ce, %dx
-       outw    %ax, %dx
-       incw    %dx
-       inb     %dx, %al
-       cmpb    $0x20, %al
-       je      isahed
-
-       cmpb    $0x21, %al
-       je      isahed
-       
-       xorw    %bp, %bp
-isahed:        ret
-
-ahead_md:
-       .byte   0x22, 0x2c, 0x84
-       .byte   0x23, 0x19, 0x84
-       .byte   0x24, 0x1c, 0x84
-       .byte   0x2f, 0x32, 0xa0
-       .byte   0x32, 0x22, 0x50
-       .byte   0x34, 0x42, 0x50
-       .byte   0
-       .ascii  "Ahead"
-       .byte   0
-
-# Chips & Tech.
-chips_test:
-       movw    $0x3c3, %dx
-       inb     %dx, %al
-       orb     $0x10, %al
-       outb    %al, %dx
-       movw    $0x104, %dx
-       inb     %dx, %al
-       movb    %al, %bl
-       movw    $0x3c3, %dx
-       inb     %dx, %al
-       andb    $0xef, %al
-       outb    %al, %dx
-       cmpb    $0xa5, %bl
-       je      cantok
-       
-       xorw    %bp, %bp
-cantok:        ret
-
-chips_md:
-       .byte   0x60, 0x19, 0x84
-       .byte   0x61, 0x32, 0x84
-       .byte   0
-       .ascii  "Chips & Technologies"
-       .byte   0
-
-# Cirrus Logic 5X0
-cirrus1_test:
-       movw    $0x3d4, %dx
-       movb    $0x0c, %al
-       outb    %al, %dx
-       incw    %dx
-       inb     %dx, %al
-       movb    %al, %bl
-       xorb    %al, %al
-       outb    %al, %dx
-       decw    %dx
-       movb    $0x1f, %al
-       outb    %al, %dx
-       incw    %dx
-       inb     %dx, %al
-       movb    %al, %bh
-       xorb    %ah, %ah
-       shlb    $4, %al
-       movw    %ax, %cx
-       movb    %bh, %al
-       shrb    $4, %al
-       addw    %ax, %cx
-       shlw    $8, %cx
-       addw    $6, %cx
-       movw    %cx, %ax
-       movw    $0x3c4, %dx
-       outw    %ax, %dx
-       incw    %dx
-       inb     %dx, %al
-       andb    %al, %al
-       jnz     nocirr
-       
-       movb    %bh, %al
-       outb    %al, %dx
-       inb     %dx, %al
-       cmpb    $0x01, %al
-       je      iscirr
-
-nocirr:        xorw    %bp, %bp
-iscirr: movw   $0x3d4, %dx
-       movb    %bl, %al
-       xorb    %ah, %ah
-       shlw    $8, %ax
-       addw    $0x0c, %ax
-       outw    %ax, %dx
-       ret
-
-cirrus1_md:
-       .byte   0x1f, 0x19, 0x84
-       .byte   0x20, 0x2c, 0x84
-       .byte   0x22, 0x1e, 0x84
-       .byte   0x31, 0x25, 0x64
-       .byte   0
-       .ascii  "Cirrus Logic 5X0"
-       .byte   0
-
-# Cirrus Logic 54XX
-cirrus5_test:
-       movw    $0x3c4, %dx
-       movb    $6, %al
-       call    inidx
-       movb    %al, %bl                        # BL=backup
-       movw    $6, %ax
-       call    tstidx
-       cmpb    $0x0f, %al
-       jne     c5fail
-       
-       movw    $0x1206, %ax
-       call    tstidx
-       cmpb    $0x12, %al
-       jne     c5fail
-       
-       movb    $0x1e, %al
-       call    inidx
-       movb    %al, %bh
-       movb    %bh, %ah
-       andb    $0xc0, %ah
-       movb    $0x1e, %al
-       call    tstidx
-       andb    $0x3f, %al
-       jne     c5xx
-       
-       movb    $0x1e, %al
-       movb    %bh, %ah
-       orb     $0x3f, %ah
-       call    tstidx
-       xorb    $0x3f, %al
-       andb    $0x3f, %al
-c5xx:  pushf
-       movb    $0x1e, %al
-       movb    %bh, %ah
-       outw    %ax, %dx
-       popf
-       je      c5done
-
-c5fail:        xorw    %bp, %bp
-c5done:        movb    $6, %al
-       movb    %bl, %ah
-       outw    %ax, %dx
-       ret
-
-cirrus5_md:
-       .byte   0x14, 0x19, 0x84
-       .byte   0x54, 0x2b, 0x84
-       .byte   0
-       .ascii  "Cirrus Logic 54XX"
-       .byte   0
-
-# Cirrus Logic 64XX -- no known extra modes, but must be identified, because
-# it's misidentified by the Ahead test.
-cirrus6_test:
-       movw    $0x3ce, %dx
-       movb    $0x0a, %al
-       call    inidx
-       movb    %al, %bl        # BL=backup
-       movw    $0xce0a, %ax
-       call    tstidx
-       orb     %al, %al
-       jne     c2fail
-       
-       movw    $0xec0a, %ax
-       call    tstidx
-       cmpb    $0x01, %al
-       jne     c2fail
-       
-       movb    $0xaa, %al
-       call    inidx           # 4X, 5X, 7X and 8X are valid 64XX chip ID's. 
-       shrb    $4, %al
-       subb    $4, %al
-       jz      c6done
-       
-       decb    %al
-       jz      c6done
-       
-       subb    $2, %al
-       jz      c6done
-       
-       decb    %al
-       jz      c6done
-       
-c2fail:        xorw    %bp, %bp
-c6done:        movb    $0x0a, %al
-       movb    %bl, %ah
-       outw    %ax, %dx
-       ret
-
-cirrus6_md:
-       .byte   0
-       .ascii  "Cirrus Logic 64XX"
-       .byte   0
-
-# Everex / Trident
-everex_test:
-       movw    $0x7000, %ax
-       xorw    %bx, %bx
-       int     $0x10
-       cmpb    $0x70, %al
-       jne     noevrx
-       
-       shrw    $4, %dx
-       cmpw    $0x678, %dx
-       je      evtrid
-       
-       cmpw    $0x236, %dx
-       jne     evrxok
-
-evtrid:        leaw    trident_md, %bp
-evrxok:        ret
-
-noevrx:        xorw    %bp, %bp
-       ret
-
-everex_md:
-       .byte   0x03, 0x22, 0x50
-       .byte   0x04, 0x3c, 0x50
-       .byte   0x07, 0x2b, 0x64
-       .byte   0x08, 0x4b, 0x64
-       .byte   0x0a, 0x19, 0x84
-       .byte   0x0b, 0x2c, 0x84
-       .byte   0x16, 0x1e, 0x50
-       .byte   0x18, 0x1b, 0x64
-       .byte   0x21, 0x40, 0xa0
-       .byte   0x40, 0x1e, 0x84
-       .byte   0
-       .ascii  "Everex/Trident"
-       .byte   0
-
-# Genoa.
-genoa_test:
-       leaw    idgenoa, %si                    # Check Genoa 'clues'
-       xorw    %ax, %ax
-       movb    %es:(0x37), %al
-       movw    %ax, %di
-       movw    $0x04, %cx
-       decw    %si
-       decw    %di
-l1:    incw    %si
-       incw    %di
-       movb    (%si), %al
-       testb   %al, %al
-       jz      l2
-
-       cmpb    %es:(%di), %al
-l2:    loope   l1
-       orw     %cx, %cx
-       je      isgen
-       
-       xorw    %bp, %bp
-isgen: ret
-
-idgenoa: .byte 0x77, 0x00, 0x99, 0x66
-
-genoa_md:
-       .byte   0x58, 0x20, 0x50
-       .byte   0x5a, 0x2a, 0x64
-       .byte   0x60, 0x19, 0x84
-       .byte   0x61, 0x1d, 0x84
-       .byte   0x62, 0x20, 0x84
-       .byte   0x63, 0x2c, 0x84
-       .byte   0x64, 0x3c, 0x84
-       .byte   0x6b, 0x4f, 0x64
-       .byte   0x72, 0x3c, 0x50
-       .byte   0x74, 0x42, 0x50
-       .byte   0x78, 0x4b, 0x64
-       .byte   0
-       .ascii  "Genoa"
-       .byte   0
-
-# OAK
-oak_test:
-       leaw    idoakvga, %si
-       movw    $0x08, %di
-       movw    $0x08, %cx
-       repe
-       cmpsb
-       je      isoak
-       
-       xorw    %bp, %bp
-isoak: ret
-
-idoakvga: .ascii  "OAK VGA "
-
-oak_md: .byte  0x4e, 0x3c, 0x50
-       .byte   0x4f, 0x3c, 0x84
-       .byte   0x50, 0x19, 0x84
-       .byte   0x51, 0x2b, 0x84
-       .byte   0
-       .ascii  "OAK"
-       .byte   0
-
-# WD Paradise.
-paradise_test:
-       leaw    idparadise, %si
-       movw    $0x7d, %di
-       movw    $0x04, %cx
-       repe
-       cmpsb
-       je      ispara
-       
-       xorw    %bp, %bp
-ispara:        ret
-
-idparadise:    .ascii  "VGA="
-
-paradise_md:
-       .byte   0x41, 0x22, 0x50
-       .byte   0x47, 0x1c, 0x84
-       .byte   0x55, 0x19, 0x84
-       .byte   0x54, 0x2c, 0x84
-       .byte   0
-       .ascii  "Paradise"
-       .byte   0
-
-# Trident.
-trident_test:
-       movw    $0x3c4, %dx
-       movb    $0x0e, %al
-       outb    %al, %dx
-       incw    %dx
-       inb     %dx, %al
-       xchgb   %al, %ah
-       xorb    %al, %al
-       outb    %al, %dx
-       inb     %dx, %al
-       xchgb   %ah, %al
-       movb    %al, %bl        # Strange thing ... in the book this wasn't
-       andb    $0x02, %bl      # necessary but it worked on my card which
-       jz      setb2           # is a trident. Without it the screen goes
-                               # blurred ...
-       andb    $0xfd, %al
-       jmp     clrb2           
-
-setb2: orb     $0x02, %al      
-clrb2: outb    %al, %dx
-       andb    $0x0f, %ah
-       cmpb    $0x02, %ah
-       je      istrid
-
-       xorw    %bp, %bp
-istrid:        ret
-
-trident_md:
-       .byte   0x50, 0x1e, 0x50
-       .byte   0x51, 0x2b, 0x50
-       .byte   0x52, 0x3c, 0x50
-       .byte   0x57, 0x19, 0x84
-       .byte   0x58, 0x1e, 0x84
-       .byte   0x59, 0x2b, 0x84
-       .byte   0x5a, 0x3c, 0x84
-       .byte   0
-       .ascii  "Trident"
-       .byte   0
-
-# Tseng.
-tseng_test:
-       movw    $0x3cd, %dx
-       inb     %dx, %al        # Could things be this simple ! :-)
-       movb    %al, %bl
-       movb    $0x55, %al
-       outb    %al, %dx
-       inb     %dx, %al
-       movb    %al, %ah
-       movb    %bl, %al
-       outb    %al, %dx
-       cmpb    $0x55, %ah
-       je      istsen
-
-isnot: xorw    %bp, %bp
-istsen:        ret
-
-tseng_md:
-       .byte   0x26, 0x3c, 0x50
-       .byte   0x2a, 0x28, 0x64
-       .byte   0x23, 0x19, 0x84
-       .byte   0x24, 0x1c, 0x84
-       .byte   0x22, 0x2c, 0x84
-       .byte   0x21, 0x3c, 0x84
-       .byte   0
-       .ascii  "Tseng"
-       .byte   0
-
-# Video7.
-video7_test:
-       movw    $0x3cc, %dx
-       inb     %dx, %al
-       movw    $0x3b4, %dx
-       andb    $0x01, %al
-       jz      even7
-
-       movw    $0x3d4, %dx
-even7: movb    $0x0c, %al
-       outb    %al, %dx
-       incw    %dx
-       inb     %dx, %al
-       movb    %al, %bl
-       movb    $0x55, %al
-       outb    %al, %dx
-       inb     %dx, %al
-       decw    %dx
-       movb    $0x1f, %al
-       outb    %al, %dx
-       incw    %dx
-       inb     %dx, %al
-       movb    %al, %bh
-       decw    %dx
-       movb    $0x0c, %al
-       outb    %al, %dx
-       incw    %dx
-       movb    %bl, %al
-       outb    %al, %dx
-       movb    $0x55, %al
-       xorb    $0xea, %al
-       cmpb    %bh, %al
-       jne     isnot
-       
-       movb    $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
-       ret
-
-video7_md:
-       .byte   0x40, 0x2b, 0x50
-       .byte   0x43, 0x3c, 0x50
-       .byte   0x44, 0x3c, 0x64
-       .byte   0x41, 0x19, 0x84
-       .byte   0x42, 0x2c, 0x84
-       .byte   0x45, 0x1c, 0x84
-       .byte   0
-       .ascii  "Video 7"
-       .byte   0
-
-# Realtek VGA
-realtek_test:
-       leaw    idrtvga, %si
-       movw    $0x45, %di
-       movw    $0x0b, %cx
-       repe
-       cmpsb
-       je      isrt
-       
-       xorw    %bp, %bp
-isrt:  ret
-
-idrtvga:       .ascii  "REALTEK VGA"
-
-realtek_md:
-       .byte   0x1a, 0x3c, 0x50
-       .byte   0x1b, 0x19, 0x84
-       .byte   0x1c, 0x1e, 0x84
-       .byte   0x1d, 0x2b, 0x84
-       .byte   0x1e, 0x3c, 0x84
-       .byte   0
-       .ascii  "REALTEK"
-       .byte   0
-
-#endif /* CONFIG_VIDEO_SVGA */
-
-# User-defined local mode table (VGA only)
-#ifdef CONFIG_VIDEO_LOCAL
-local_modes:
-       leaw    local_mode_table, %si
-locm1: lodsw
-       orw     %ax, %ax
-       jz      locm2
-       
-       stosw
-       movsw
-       jmp     locm1
-
-locm2: ret
-
-# This is the table of local video modes which can be supplied manually
-# by the user. Each entry consists of mode ID (word) and dimensions
-# (byte for column count and another byte for row count). These modes
-# are placed before all SVGA and VESA modes and override them if table
-# compacting is enabled. The table must end with a zero word followed
-# by NUL-terminated video adapter name.
-local_mode_table:
-       .word   0x0100                          # Example: 40x25
-       .byte   25,40
-       .word   0
-       .ascii  "Local"
-       .byte   0
-#endif /* CONFIG_VIDEO_LOCAL */
-
-# Read a key and return the ASCII code in al, scan code in ah
-getkey:        xorb    %ah, %ah
-       int     $0x16
-       ret
-
-# Read a key with a timeout of 30 seconds.
-# The hardware clock is used to get the time.
-getkt: call    gettime
-       addb    $30, %al                        # Wait 30 seconds
-       cmpb    $60, %al
-       jl      lminute
-
-       subb    $60, %al
-lminute:
-       movb    %al, %cl
-again: movb    $0x01, %ah
-       int     $0x16
-       jnz     getkey                          # key pressed, so get it
-
-       call    gettime
-       cmpb    %cl, %al
-       jne     again
-
-       movb    $0x20, %al                      # timeout, return `space'
-       ret
-
-# Flush the keyboard buffer
-flush: movb    $0x01, %ah
-       int     $0x16
-       jz      empty
-       
-       xorb    %ah, %ah
-       int     $0x16
-       jmp     flush
-
-empty: ret
-
-# Print hexadecimal number.
-prthw: pushw   %ax
-       movb    %ah, %al
-       call    prthb
-       popw    %ax
-prthb: pushw   %ax
-       shrb    $4, %al
-       call    prthn
-       popw    %ax
-       andb    $0x0f, %al
-prthn: cmpb    $0x0a, %al
-       jc      prth1
-
-       addb    $0x07, %al
-prth1: addb    $0x30, %al
-       jmp     prtchr
-
-# Print decimal number in al
-prtdec:        pushw   %ax
-       pushw   %cx
-       xorb    %ah, %ah
-       movb    $0x0a, %cl
-       idivb   %cl
-       cmpb    $0x09, %al
-       jbe     lt100
-
-       call    prtdec
-       jmp     skip10
-
-lt100: addb    $0x30, %al
-       call    prtchr
-skip10:        movb    %ah, %al
-       addb    $0x30, %al
-       call    prtchr  
-       popw    %cx
-       popw    %ax
-       ret
-
-store_edid:
-#ifdef CONFIG_FIRMWARE_EDID
-       pushw   %es                             # just save all registers
-       pushw   %ax
-       pushw   %bx
-       pushw   %cx
-       pushw   %dx
-       pushw   %di
-
-       pushw   %fs
-       popw    %es
-
-       movl    $0x13131313, %eax               # memset block with 0x13
-       movw    $32, %cx
-       movw    $0x140, %di
-       cld
-       rep
-       stosl
-
-       cmpw    $0x0200, vbe_version            # only do EDID on >= VBE2.0
-       jl      no_edid
-
-       pushw   %es                             # save ES
-       xorw    %di, %di                        # Report Capability
-       pushw   %di
-       popw    %es                             # ES:DI must be 0:0
-       movw    $0x4f15, %ax
-       xorw    %bx, %bx
-       xorw    %cx, %cx
-       int     $0x10
-       popw    %es                             # restore ES
-
-       cmpb    $0x00, %ah                      # call successful
-       jne     no_edid
-
-       cmpb    $0x4f, %al                      # function supported
-       jne     no_edid
-
-       movw    $0x4f15, %ax                    # do VBE/DDC
-       movw    $0x01, %bx
-       movw    $0x00, %cx
-       movw    $0x00, %dx
-       movw    $0x140, %di
-       int     $0x10
-
-no_edid:
-       popw    %di                             # restore all registers
-       popw    %dx
-       popw    %cx
-       popw    %bx
-       popw    %ax
-       popw    %es
-#endif
-       ret
-
-# VIDEO_SELECT-only variables
-mt_end:                .word   0       # End of video mode table if built
-edit_buf:      .space  6       # Line editor buffer
-card_name:     .word   0       # Pointer to adapter name
-scanning:      .byte   0       # Performing mode scan
-do_restore:    .byte   0       # Screen contents altered during mode change
-svga_prefix:   .byte   VIDEO_FIRST_BIOS>>8     # Default prefix for BIOS modes
-graphic_mode:  .byte   0       # Graphic mode with a linear frame buffer
-dac_size:      .byte   6       # DAC bit depth
-vbe_version:   .word   0       # VBE bios version
-
-# Status messages
-keymsg:                .ascii  "Press <RETURN> to see video modes available, "
-               .ascii  "<SPACE> to continue or wait 30 secs"
-               .byte   0x0d, 0x0a, 0
-
-listhdr:       .byte   0x0d, 0x0a
-               .ascii  "Mode:    COLSxROWS:"
-
-crlft:         .byte   0x0d, 0x0a, 0
-
-prompt:                .byte   0x0d, 0x0a
-               .asciz  "Enter mode number or `scan': "
-
-unknt:         .asciz  "Unknown mode ID. Try again."
-
-badmdt:                .ascii  "You passed an undefined mode number."
-               .byte   0x0d, 0x0a, 0
-
-vesaer:                .ascii  "Error: Scanning of VESA modes failed. Please "
-               .ascii  "report to <mj@ucw.cz>."
-               .byte   0x0d, 0x0a, 0
-
-old_name:      .asciz  "CGA/MDA/HGA"
-
-ega_name:      .asciz  "EGA"
-
-svga_name:     .ascii  " "
-
-vga_name:      .asciz  "VGA"
-
-vesa_name:     .asciz  "VESA"
-
-name_bann:     .asciz  "Video adapter: "
-#endif /* CONFIG_VIDEO_SELECT */
-
-# Other variables:
-adapter:       .byte   0       # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
-video_segment: .word   0xb800  # Video memory segment
-force_size:    .word   0       # Use this size instead of the one in BIOS vars
diff --git a/arch/i386/boot/video.c b/arch/i386/boot/video.c
new file mode 100644 (file)
index 0000000..3bb3573
--- /dev/null
@@ -0,0 +1,456 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video.c
+ *
+ * Select video mode
+ */
+
+#include "boot.h"
+#include "video.h"
+#include "vesa.h"
+
+/*
+ * Mode list variables
+ */
+static struct card_info cards[];    /* List of cards to probe for */
+
+/*
+ * Common variables
+ */
+int adapter;                   /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
+u16 video_segment;
+int force_x, force_y;  /* Don't query the BIOS for cols/rows */
+
+int do_restore = 0;    /* Screen contents changed during mode flip */
+int graphic_mode;      /* Graphic mode with linear frame buffer */
+
+static void store_cursor_position(void)
+{
+       u16 curpos;
+       u16 ax, bx;
+
+       ax = 0x0300;
+       bx = 0;
+       asm(INT10
+           : "=d" (curpos), "+a" (ax), "+b" (bx)
+           : : "ecx", "esi", "edi");
+
+       boot_params.screen_info.orig_x = curpos;
+       boot_params.screen_info.orig_y = curpos >> 8;
+}
+
+static void store_video_mode(void)
+{
+       u16 ax, page;
+
+       /* N.B.: the saving of the video page here is a bit silly,
+          since we pretty much assume page 0 everywhere. */
+       ax = 0x0f00;
+       asm(INT10
+           : "+a" (ax), "=b" (page)
+           : : "ecx", "edx", "esi", "edi");
+
+       /* Not all BIOSes are clean with respect to the top bit */
+       boot_params.screen_info.orig_video_mode = ax & 0x7f;
+       boot_params.screen_info.orig_video_page = page;
+}
+
+/*
+ * Store the video mode parameters for later usage by the kernel.
+ * This is done by asking the BIOS except for the rows/columns
+ * parameters in the default 80x25 mode -- these are set directly,
+ * because some very obscure BIOSes supply insane values.
+ */
+static void store_mode_params(void)
+{
+       u16 font_size;
+       int x, y;
+
+       /* For graphics mode, it is up to the mode-setting driver
+          (currently only video-vesa.c) to store the parameters */
+       if (graphic_mode)
+               return;
+
+       store_cursor_position();
+       store_video_mode();
+
+       if (boot_params.screen_info.orig_video_mode == 0x07) {
+               /* MDA, HGC, or VGA in monochrome mode */
+               video_segment = 0xb000;
+       } else {
+               /* CGA, EGA, VGA and so forth */
+               video_segment = 0xb800;
+       }
+
+       set_fs(0);
+       font_size = rdfs16(0x485); /* Font size, BIOS area */
+       boot_params.screen_info.orig_video_points = font_size;
+
+       x = rdfs16(0x44a);
+       y = (adapter == ADAPTER_CGA) ? 25 : rdfs8(0x484)+1;
+
+       if (force_x)
+               x = force_x;
+       if (force_y)
+               y = force_y;
+
+       boot_params.screen_info.orig_video_cols  = x;
+       boot_params.screen_info.orig_video_lines = y;
+}
+
+/* Probe the video drivers and have them generate their mode lists. */
+static void probe_cards(int unsafe)
+{
+       struct card_info *card;
+       static u8 probed[2];
+
+       if (probed[unsafe])
+               return;
+
+       probed[unsafe] = 1;
+
+       for (card = video_cards; card < video_cards_end; card++) {
+               if (card->unsafe == unsafe) {
+                       if (card->probe)
+                               card->nmodes = card->probe();
+                       else
+                               card->nmodes = 0;
+               }
+       }
+}
+
+/* Test if a mode is defined */
+int mode_defined(u16 mode)
+{
+       struct card_info *card;
+       struct mode_info *mi;
+       int i;
+
+       for (card = video_cards; card < video_cards_end; card++) {
+               mi = card->modes;
+               for (i = 0; i < card->nmodes; i++, mi++) {
+                       if (mi->mode == mode)
+                               return 1;
+               }
+       }
+
+       return 0;
+}
+
+/* Set mode (without recalc) */
+static int raw_set_mode(u16 mode)
+{
+       int nmode, i;
+       struct card_info *card;
+       struct mode_info *mi;
+
+       /* Drop the recalc bit if set */
+       mode &= ~VIDEO_RECALC;
+
+       /* Scan for mode based on fixed ID, position, or resolution */
+       nmode = 0;
+       for (card = video_cards; card < video_cards_end; card++) {
+               mi = card->modes;
+               for (i = 0; i < card->nmodes; i++, mi++) {
+                       int visible = mi->x || mi->y;
+
+                       if ((mode == nmode && visible) ||
+                           mode == mi->mode ||
+                           mode == (mi->y << 8)+mi->x)
+                               return card->set_mode(mi);
+
+                       if (visible)
+                               nmode++;
+               }
+       }
+
+       /* Nothing found?  Is it an "exceptional" (unprobed) mode? */
+       for (card = video_cards; card < video_cards_end; card++) {
+               if (mode >= card->xmode_first &&
+                   mode < card->xmode_first+card->xmode_n) {
+                       struct mode_info mix;
+                       mix.mode = mode;
+                       mix.x = mix.y = 0;
+                       return card->set_mode(&mix);
+               }
+       }
+
+       /* Otherwise, failure... */
+       return -1;
+}
+
+/*
+ * Recalculate the vertical video cutoff (hack!)
+ */
+static void vga_recalc_vertical(void)
+{
+       unsigned int font_size, rows;
+       u16 crtc;
+       u8 ov;
+
+       set_fs(0);
+       font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
+       rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
+
+       rows *= font_size;      /* Visible scan lines */
+       rows--;                 /* ... minus one */
+
+       crtc = vga_crtc();
+
+       out_idx((u8)rows, crtc, 0x12); /* Lower height register */
+       ov = in_idx(crtc, 0x07); /* Overflow register */
+       ov &= 0xbd;
+       ov |= (rows >> (8-1)) & 0x02;
+       ov |= (rows >> (9-6)) & 0x40;
+       out_idx(ov, crtc, 0x07);
+}
+
+/* Set mode (with recalc if specified) */
+static int set_mode(u16 mode)
+{
+       int rv;
+
+       /* Very special mode numbers... */
+       if (mode == VIDEO_CURRENT_MODE)
+               return 0;       /* Nothing to do... */
+       else if (mode == NORMAL_VGA)
+               mode = VIDEO_80x25;
+       else if (mode == EXTENDED_VGA)
+               mode = VIDEO_8POINT;
+
+       rv = raw_set_mode(mode);
+       if (rv)
+               return rv;
+
+       if (mode & VIDEO_RECALC)
+               vga_recalc_vertical();
+
+       return 0;
+}
+
+static unsigned int get_entry(void)
+{
+       char entry_buf[4];
+       int i, len = 0;
+       int key;
+       unsigned int v;
+
+       do {
+               key = getchar();
+
+               if (key == '\b') {
+                       if (len > 0) {
+                               puts("\b \b");
+                               len--;
+                       }
+               } else if ((key >= '0' && key <= '9') ||
+                          (key >= 'A' && key <= 'Z') ||
+                          (key >= 'a' && key <= 'z')) {
+                       if (len < sizeof entry_buf) {
+                               entry_buf[len++] = key;
+                               putchar(key);
+                       }
+               }
+       } while (key != '\r');
+       putchar('\n');
+
+       if (len == 0)
+               return VIDEO_CURRENT_MODE; /* Default */
+
+       v = 0;
+       for (i = 0; i < len; i++) {
+               v <<= 4;
+               key = entry_buf[i] | 0x20;
+               v += (key > '9') ? key-'a'+10 : key-'0';
+       }
+
+       return v;
+}
+
+static void display_menu(void)
+{
+       struct card_info *card;
+       struct mode_info *mi;
+       char ch;
+       int i;
+
+       puts("Mode:    COLSxROWS:\n");
+
+       ch = '0';
+       for (card = video_cards; card < video_cards_end; card++) {
+               mi = card->modes;
+               for (i = 0; i < card->nmodes; i++, mi++) {
+                       int visible = mi->x && mi->y;
+                       u16 mode_id = mi->mode ? mi->mode :
+                               (mi->y << 8)+mi->x;
+
+                       if (!visible)
+                               continue; /* Hidden mode */
+
+                       printf("%c  %04X  %3dx%-3d  %s\n",
+                              ch, mode_id, mi->x, mi->y, card->card_name);
+
+                       if (ch == '9')
+                               ch = 'a';
+                       else if (ch == 'z' || ch == ' ')
+                               ch = ' '; /* Out of keys... */
+                       else
+                               ch++;
+               }
+       }
+}
+
+#define H(x)   ((x)-'a'+10)
+#define SCAN   ((H('s')<<12)+(H('c')<<8)+(H('a')<<4)+H('n'))
+
+static unsigned int mode_menu(void)
+{
+       int key;
+       unsigned int sel;
+
+       puts("Press <ENTER> to see video modes available, "
+            "<SPACE> to continue, or wait 30 sec\n");
+
+       kbd_flush();
+       while (1) {
+               key = getchar_timeout();
+               if (key == ' ' || key == 0)
+                       return VIDEO_CURRENT_MODE; /* Default */
+               if (key == '\r')
+                       break;
+               putchar('\a');  /* Beep! */
+       }
+
+
+       for (;;) {
+               display_menu();
+
+               puts("Enter a video mode or \"scan\" to scan for "
+                    "additional modes: ");
+               sel = get_entry();
+               if (sel != SCAN)
+                       return sel;
+
+               probe_cards(1);
+       }
+}
+
+#ifdef CONFIG_VIDEO_RETAIN
+/* Save screen content to the heap */
+struct saved_screen {
+       int x, y;
+       int curx, cury;
+       u16 *data;
+} saved;
+
+static void save_screen(void)
+{
+       /* Should be called after store_mode_params() */
+       saved.x = boot_params.screen_info.orig_video_cols;
+       saved.y = boot_params.screen_info.orig_video_lines;
+       saved.curx = boot_params.screen_info.orig_x;
+       saved.cury = boot_params.screen_info.orig_y;
+
+       if (heap_free() < saved.x*saved.y*sizeof(u16)+512)
+               return;         /* Not enough heap to save the screen */
+
+       saved.data = GET_HEAP(u16, saved.x*saved.y);
+
+       set_fs(video_segment);
+       copy_from_fs(saved.data, 0, saved.x*saved.y*sizeof(u16));
+}
+
+static void restore_screen(void)
+{
+       /* Should be called after store_mode_params() */
+       int xs = boot_params.screen_info.orig_video_cols;
+       int ys = boot_params.screen_info.orig_video_lines;
+       int y;
+       addr_t dst = 0;
+       u16 *src = saved.data;
+       u16 ax, bx, dx;
+
+       if (graphic_mode)
+               return;         /* Can't restore onto a graphic mode */
+
+       if (!src)
+               return;         /* No saved screen contents */
+
+       /* Restore screen contents */
+
+       set_fs(video_segment);
+       for (y = 0; y < ys; y++) {
+               int npad;
+
+               if (y < saved.y) {
+                       int copy = (xs < saved.x) ? xs : saved.x;
+                       copy_to_fs(dst, src, copy*sizeof(u16));
+                       dst += copy*sizeof(u16);
+                       src += saved.x;
+                       npad = (xs < saved.x) ? 0 : xs-saved.x;
+               } else {
+                       npad = xs;
+               }
+
+               /* Writes "npad" blank characters to
+                  video_segment:dst and advances dst */
+               asm volatile("pushw %%es ; "
+                            "movw %2,%%es ; "
+                            "shrw %%cx ; "
+                            "jnc 1f ; "
+                            "stosw \n\t"
+                            "1: rep;stosl ; "
+                            "popw %%es"
+                            : "+D" (dst), "+c" (npad)
+                            : "bdSm" (video_segment),
+                              "a" (0x07200720));
+       }
+
+       /* Restore cursor position */
+       ax = 0x0200;            /* Set cursor position */
+       bx = 0;                 /* Page number (<< 8) */
+       dx = (saved.cury << 8)+saved.curx;
+       asm volatile(INT10
+                    : "+a" (ax), "+b" (bx), "+d" (dx)
+                    : : "ecx", "esi", "edi");
+}
+#else
+#define save_screen()          ((void)0)
+#define restore_screen()       ((void)0)
+#endif
+
+void set_video(void)
+{
+       u16 mode = boot_params.hdr.vid_mode;
+
+       RESET_HEAP();
+
+       store_mode_params();
+       save_screen();
+       probe_cards(0);
+
+       for (;;) {
+               if (mode == ASK_VGA)
+                       mode = mode_menu();
+
+               if (!set_mode(mode))
+                       break;
+
+               printf("Undefined video mode number: %x\n", mode);
+               mode = ASK_VGA;
+       }
+       vesa_store_edid();
+       store_mode_params();
+
+       if (do_restore)
+               restore_screen();
+}
diff --git a/arch/i386/boot/video.h b/arch/i386/boot/video.h
new file mode 100644 (file)
index 0000000..29eca17
--- /dev/null
@@ -0,0 +1,145 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video.h
+ *
+ * Header file for the real-mode video probing code
+ */
+
+#ifndef BOOT_VIDEO_H
+#define BOOT_VIDEO_H
+
+#include <linux/types.h>
+
+/* Enable autodetection of SVGA adapters and modes. */
+#undef CONFIG_VIDEO_SVGA
+
+/* Enable autodetection of VESA modes */
+#define CONFIG_VIDEO_VESA
+
+/* Retain screen contents when switching modes */
+#define CONFIG_VIDEO_RETAIN
+
+/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
+#undef CONFIG_VIDEO_400_HACK
+
+/* This code uses an extended set of video mode numbers. These include:
+ * Aliases for standard modes
+ *      NORMAL_VGA (-1)
+ *      EXTENDED_VGA (-2)
+ *      ASK_VGA (-3)
+ * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
+ * of compatibility when extending the table. These are between 0x00 and 0xff.
+ */
+#define VIDEO_FIRST_MENU 0x0000
+
+/* Standard BIOS video modes (BIOS number + 0x0100) */
+#define VIDEO_FIRST_BIOS 0x0100
+
+/* VESA BIOS video modes (VESA number + 0x0200) */
+#define VIDEO_FIRST_VESA 0x0200
+
+/* Video7 special modes (BIOS number + 0x0900) */
+#define VIDEO_FIRST_V7 0x0900
+
+/* Special video modes */
+#define VIDEO_FIRST_SPECIAL 0x0f00
+#define VIDEO_80x25 0x0f00
+#define VIDEO_8POINT 0x0f01
+#define VIDEO_80x43 0x0f02
+#define VIDEO_80x28 0x0f03
+#define VIDEO_CURRENT_MODE 0x0f04
+#define VIDEO_80x30 0x0f05
+#define VIDEO_80x34 0x0f06
+#define VIDEO_80x60 0x0f07
+#define VIDEO_GFX_HACK 0x0f08
+#define VIDEO_LAST_SPECIAL 0x0f09
+
+/* Video modes given by resolution */
+#define VIDEO_FIRST_RESOLUTION 0x1000
+
+/* The "recalculate timings" flag */
+#define VIDEO_RECALC 0x8000
+
+/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
+#ifdef CONFIG_VIDEO_RETAIN
+void store_screen(void);
+#define DO_STORE() store_screen()
+#else
+#define DO_STORE() ((void)0)
+#endif /* CONFIG_VIDEO_RETAIN */
+
+/*
+ * Mode table structures
+ */
+
+struct mode_info {
+       u16 mode;               /* Mode number (vga= style) */
+       u8  x, y;               /* Width, height */
+};
+
+struct card_info {
+       const char *card_name;
+       int (*set_mode)(struct mode_info *mode);
+       int (*probe)(void);
+       struct mode_info *modes;
+       int nmodes;             /* Number of probed modes so far */
+       int unsafe;             /* Probing is unsafe, only do after "scan" */
+       u16 xmode_first;        /* Unprobed modes to try to call anyway */
+       u16 xmode_n;            /* Size of unprobed mode range */
+};
+
+#define __videocard struct card_info __attribute__((section(".videocards")))
+extern struct card_info video_cards[], video_cards_end[];
+
+int mode_defined(u16 mode);    /* video.c */
+
+/* Basic video information */
+#define ADAPTER_CGA    0       /* CGA/MDA/HGC */
+#define ADAPTER_EGA    1
+#define ADAPTER_VGA    2
+
+extern int adapter;
+extern u16 video_segment;
+extern int force_x, force_y;   /* Don't query the BIOS for cols/rows */
+extern int do_restore;         /* Restore screen contents */
+extern int graphic_mode;       /* Graphics mode with linear frame buffer */
+
+/*
+ * int $0x10 is notorious for touching registers it shouldn't.
+ * gcc doesn't like %ebp being clobbered, so define it as a push/pop
+ * sequence here.
+ */
+#define INT10 "pushl %%ebp; int $0x10; popl %%ebp"
+
+/* Accessing VGA indexed registers */
+static inline u8 in_idx(u16 port, u8 index)
+{
+       outb(index, port);
+       return inb(port+1);
+}
+
+static inline void out_idx(u8 v, u16 port, u8 index)
+{
+       outw(index+(v << 8), port);
+}
+
+/* Writes a value to an indexed port and then reads the port again */
+static inline u8 tst_idx(u8 v, u16 port, u8 index)
+{
+       out_idx(port, index, v);
+       return in_idx(port, index);
+}
+
+/* Get the I/O port of the VGA CRTC */
+u16 vga_crtc(void);            /* video-vga.c */
+
+#endif /* BOOT_VIDEO_H */
diff --git a/arch/i386/boot/voyager.c b/arch/i386/boot/voyager.c
new file mode 100644 (file)
index 0000000..9221614
--- /dev/null
@@ -0,0 +1,46 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/voyager.c
+ *
+ * Get the Voyager config information
+ */
+
+#include "boot.h"
+
+#ifdef CONFIG_X86_VOYAGER
+
+int query_voyager(void)
+{
+       u8 err;
+       u16 es, di;
+       /* Abuse the apm_bios_info area for this */
+       u8 *data_ptr = (u8 *)&boot_params.apm_bios_info;
+
+       data_ptr[0] = 0xff;     /* Flag on config not found(?) */
+
+       asm("pushw %%es ; "
+           "int $0x15 ; "
+           "setc %0 ; "
+           "movw %%es, %1 ; "
+           "popw %%es"
+           : "=qm" (err), "=rm" (es), "=D" (di)
+           : "a" (0xffc0));
+
+       if (err)
+               return -1;      /* Not Voyager */
+
+       set_fs(es);
+       copy_from_fs(data_ptr, di, 7);  /* Table is 7 bytes apparently */
+       return 0;
+}
+
+#endif /* CONFIG_X86_VOYAGER */
index 74f27a463db088dbccce3293a9904d7c1c646f55..0b6a8551e9e222167c44fbb8e6bd63bd0d10141c 100644 (file)
@@ -8,7 +8,7 @@ obj-y   +=      amd.o
 obj-y  +=      cyrix.o
 obj-y  +=      centaur.o
 obj-y  +=      transmeta.o
-obj-y  +=      intel.o intel_cacheinfo.o
+obj-y  +=      intel.o intel_cacheinfo.o addon_cpuid_features.o
 obj-y  +=      rise.o
 obj-y  +=      nexgen.o
 obj-y  +=      umc.o
diff --git a/arch/i386/kernel/cpu/addon_cpuid_features.c b/arch/i386/kernel/cpu/addon_cpuid_features.c
new file mode 100644 (file)
index 0000000..3e91d3e
--- /dev/null
@@ -0,0 +1,50 @@
+
+/*
+ *     Routines to indentify additional cpu features that are scattered in
+ *     cpuid space.
+ */
+
+#include <linux/cpu.h>
+
+#include <asm/processor.h>
+
+struct cpuid_bit {
+       u16 feature;
+       u8 reg;
+       u8 bit;
+       u32 level;
+};
+
+enum cpuid_regs {
+       CR_EAX = 0,
+       CR_ECX,
+       CR_EDX,
+       CR_EBX
+};
+
+void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
+{
+       u32 max_level;
+       u32 regs[4];
+       const struct cpuid_bit *cb;
+
+       static const struct cpuid_bit cpuid_bits[] = {
+               { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
+               { 0, 0, 0, 0 }
+       };
+
+       for (cb = cpuid_bits; cb->feature; cb++) {
+
+               /* Verify that the level is valid */
+               max_level = cpuid_eax(cb->level & 0xffff0000);
+               if (max_level < cb->level ||
+                   max_level > (cb->level | 0xffff))
+                       continue;
+
+               cpuid(cb->level, &regs[CR_EAX], &regs[CR_EBX],
+                       &regs[CR_ECX], &regs[CR_EDX]);
+
+               if (regs[cb->reg] & (1 << cb->bit))
+                       set_bit(cb->feature, c->x86_capability);
+       }
+}
index 794d593c47eb078acf6cf435023aabbbfef65ce1..e5419a9dec885e1d1135f1f46279e3388039a71f 100644 (file)
@@ -353,6 +353,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
                        if ( xlvl >= 0x80000004 )
                                get_model_name(c); /* Default name */
                }
+
+               init_scattered_cpuid_features(c);
        }
 
        early_intel_workaround(c);
index e912aae9473cb449480cde7a60e68b70347a6b71..094118ba00da8ee85c5e108db1d0a715564a5b1c 100644 (file)
@@ -90,10 +90,17 @@ config X86_POWERNOW_K8
          If in doubt, say N.
 
 config X86_POWERNOW_K8_ACPI
-       bool
-       depends on X86_POWERNOW_K8 && ACPI_PROCESSOR
-       depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m)
+       bool "ACPI Support"
+       select ACPI_PROCESSOR
+       depends on X86_POWERNOW_K8
        default y
+       help
+         This provides access to the K8s Processor Performance States via ACPI.
+         This driver is probably required for CPUFreq to work with multi-socket and
+         SMP systems.  It is not required on at least some single-socket yet
+         multi-core systems, even if SMP is enabled.
+
+         It is safe to say Y here.
 
 config X86_GX_SUSPMOD
        tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
@@ -109,7 +116,7 @@ config X86_GX_SUSPMOD
 config X86_SPEEDSTEP_CENTRINO
        tristate "Intel Enhanced SpeedStep"
        select CPU_FREQ_TABLE
-       select X86_SPEEDSTEP_CENTRINO_TABLE if (!X86_SPEEDSTEP_CENTRINO_ACPI)
+       select X86_SPEEDSTEP_CENTRINO_TABLE
        help
          This adds the CPUFreq driver for Enhanced SpeedStep enabled
          mobile CPUs.  This means Intel Pentium M (Centrino) CPUs. However,
@@ -121,20 +128,6 @@ config X86_SPEEDSTEP_CENTRINO
 
          If in doubt, say N.
 
-config X86_SPEEDSTEP_CENTRINO_ACPI
-       bool "Use ACPI tables to decode valid frequency/voltage (deprecated)"
-       depends on X86_SPEEDSTEP_CENTRINO && ACPI_PROCESSOR
-       depends on !(X86_SPEEDSTEP_CENTRINO = y && ACPI_PROCESSOR = m)
-       help
-         This is deprecated and this functionality is now merged into
-         acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
-         speedstep_centrino.
-         Use primarily the information provided in the BIOS ACPI tables
-         to determine valid CPU frequency and voltage pairings. It is
-         required for the driver to work on non-Banias CPUs.
-
-         If in doubt, say Y.
-
 config X86_SPEEDSTEP_CENTRINO_TABLE
        bool "Built-in tables for Banias CPUs"
        depends on X86_SPEEDSTEP_CENTRINO
@@ -230,7 +223,7 @@ comment "shared options"
 config X86_ACPI_CPUFREQ_PROC_INTF
        bool "/proc/acpi/processor/../performance interface (deprecated)"
        depends on PROC_FS
-       depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
+       depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
        help
          This enables the deprecated /proc/acpi/processor/../performance
          interface. While it is helpful for debugging, the generic,
index 10baa3501ed336c37b5d9a5662ce99484c48d651..18c8b67ea3a75ce4b5d740e1eb8a68b3cda46915 100644 (file)
@@ -167,11 +167,13 @@ static void do_drv_read(struct drv_cmd *cmd)
 
 static void do_drv_write(struct drv_cmd *cmd)
 {
-       u32 h = 0;
+       u32 lo, hi;
 
        switch (cmd->type) {
        case SYSTEM_INTEL_MSR_CAPABLE:
-               wrmsr(cmd->addr.msr.reg, cmd->val, h);
+               rdmsr(cmd->addr.msr.reg, lo, hi);
+               lo = (lo & ~INTEL_MSR_RANGE) | (cmd->val & INTEL_MSR_RANGE);
+               wrmsr(cmd->addr.msr.reg, lo, hi);
                break;
        case SYSTEM_IO_CAPABLE:
                acpi_os_write_port((acpi_io_address)cmd->addr.io.port,
@@ -372,7 +374,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
        struct cpufreq_freqs freqs;
        cpumask_t online_policy_cpus;
        struct drv_cmd cmd;
-       unsigned int msr;
        unsigned int next_state = 0; /* Index into freq_table */
        unsigned int next_perf_state = 0; /* Index into perf table */
        unsigned int i;
@@ -417,11 +418,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
        case SYSTEM_INTEL_MSR_CAPABLE:
                cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
                cmd.addr.msr.reg = MSR_IA32_PERF_CTL;
-               msr =
-                   (u32) perf->states[next_perf_state].
-                   control & INTEL_MSR_RANGE;
-               cmd.val = get_cur_val(online_policy_cpus);
-               cmd.val = (cmd.val & ~INTEL_MSR_RANGE) | msr;
+               cmd.val = (u32) perf->states[next_perf_state].control;
                break;
        case SYSTEM_IO_CAPABLE:
                cmd.type = SYSTEM_IO_CAPABLE;
index 0d49d73d1b711274387f6f23988415073774bc78..66acd5039918350d16819cbf41457053f021fe56 100644 (file)
@@ -391,8 +391,6 @@ static struct cpufreq_driver nforce2_driver = {
  */
 static unsigned int nforce2_detect_chipset(void)
 {
-       u8 revision;
-
        nforce2_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
                                        PCI_DEVICE_ID_NVIDIA_NFORCE2,
                                        PCI_ANY_ID, PCI_ANY_ID, NULL);
@@ -400,10 +398,8 @@ static unsigned int nforce2_detect_chipset(void)
        if (nforce2_chipset_dev == NULL)
                return -ENODEV;
 
-       pci_read_config_byte(nforce2_chipset_dev, PCI_REVISION_ID, &revision);
-
        printk(KERN_INFO "cpufreq: Detected nForce2 chipset revision %X\n",
-              revision);
+              nforce2_chipset_dev->revision);
        printk(KERN_INFO
               "cpufreq: FSB changing is maybe unstable and can lead to crashes and data loss.\n");
 
index 6667e9cceb9fd8c3dbfe5d75a93008b27111a997..194144539a6f34ccddd67e4e7f3393b68e5fecba 100644 (file)
@@ -115,7 +115,6 @@ struct gxfreq_params {
        u8 pci_suscfg;
        u8 pci_pmer1;
        u8 pci_pmer2;
-       u8 pci_rev;
        struct pci_dev *cs55x0;
 };
 
@@ -276,7 +275,7 @@ static void gx_set_cpuspeed(unsigned int khz)
                        pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */
                        pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1);
 
-                       if (gx_params->pci_rev < 0x10) {   /* CS5530(rev 1.2, 1.3) */
+                       if (gx_params->cs55x0->revision < 0x10) {   /* CS5530(rev 1.2, 1.3) */
                                suscfg = gx_params->pci_suscfg | SUSMOD;
                        } else {                           /* CS5530A,B.. */
                                suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE;
@@ -471,7 +470,6 @@ static int __init cpufreq_gx_init(void)
        pci_read_config_byte(params->cs55x0, PCI_PMER2, &(params->pci_pmer2));
        pci_read_config_byte(params->cs55x0, PCI_MODON, &(params->on_duration));
        pci_read_config_byte(params->cs55x0, PCI_MODOFF, &(params->off_duration));
-       pci_read_config_byte(params->cs55x0, PCI_REVISION_ID, &params->pci_rev);
 
        if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) {
                kfree(params);
index a3df9c039bd4221ecb3e80fdda4e71a8b4d9581d..ef8f0bc3fc71bd2b7ebdd936cd09960592af5870 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/delay.h>
 
 #include <asm/msr.h>
 #include <asm/timex.h>
@@ -55,7 +56,6 @@
 /* Flags */
 #define USE_ACPI_C3            (1 << 1)
 #define USE_NORTHBRIDGE                (1 << 2)
-#define USE_VT8235             (1 << 3)
 
 static int cpu_model;
 static unsigned int numscales=16;
@@ -63,22 +63,19 @@ static unsigned int fsb;
 
 static const struct mV_pos *vrm_mV_table;
 static const unsigned char *mV_vrm_table;
-struct f_msr {
-       u8 vrm;
-       u8 pos;
-};
-static struct f_msr f_msr_table[32];
 
 static unsigned int highest_speed, lowest_speed; /* kHz */
 static unsigned int minmult, maxmult;
 static int can_scale_voltage;
 static struct acpi_processor *pr = NULL;
 static struct acpi_processor_cx *cx = NULL;
+static u32 acpi_regs_addr;
 static u8 longhaul_flags;
-static u8 longhaul_pos;
+static unsigned int longhaul_index;
 
 /* Module parameters */
 static int scale_voltage;
+static int disable_acpi_c3;
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
 
@@ -144,7 +141,7 @@ static void do_longhaul1(unsigned int clock_ratio_index)
        rdmsrl(MSR_VIA_BCR2, bcr2.val);
        /* Enable software clock multiplier */
        bcr2.bits.ESOFTBF = 1;
-       bcr2.bits.CLOCKMUL = clock_ratio_index;
+       bcr2.bits.CLOCKMUL = clock_ratio_index & 0xff;
 
        /* Sync to timer tick */
        safe_halt();
@@ -163,14 +160,12 @@ static void do_longhaul1(unsigned int clock_ratio_index)
 
 /* For processor with Longhaul MSR */
 
-static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
+static void do_powersaver(int cx_address, unsigned int clock_ratio_index,
+                         unsigned int dir)
 {
        union msr_longhaul longhaul;
-       u8 dest_pos;
        u32 t;
 
-       dest_pos = f_msr_table[clock_ratio_index].pos;
-
        rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
        /* Setup new frequency */
        longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
@@ -178,11 +173,11 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
        longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
        /* Setup new voltage */
        if (can_scale_voltage)
-               longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm;
+               longhaul.bits.SoftVID = (clock_ratio_index >> 8) & 0x1f;
        /* Sync to timer tick */
        safe_halt();
        /* Raise voltage if necessary */
-       if (can_scale_voltage && longhaul_pos < dest_pos) {
+       if (can_scale_voltage && dir) {
                longhaul.bits.EnableSoftVID = 1;
                wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
                /* Change voltage */
@@ -199,7 +194,6 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
                }
                longhaul.bits.EnableSoftVID = 0;
                wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
-               longhaul_pos = dest_pos;
        }
 
        /* Change frequency on next halt or sleep */
@@ -220,7 +214,7 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
        wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 
        /* Reduce voltage if necessary */
-       if (can_scale_voltage && longhaul_pos > dest_pos) {
+       if (can_scale_voltage && !dir) {
                longhaul.bits.EnableSoftVID = 1;
                wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
                /* Change voltage */
@@ -237,7 +231,6 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
                }
                longhaul.bits.EnableSoftVID = 0;
                wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
-               longhaul_pos = dest_pos;
        }
 }
 
@@ -248,25 +241,28 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
  * Sets a new clock ratio.
  */
 
-static void longhaul_setstate(unsigned int clock_ratio_index)
+static void longhaul_setstate(unsigned int table_index)
 {
+       unsigned int clock_ratio_index;
        int speed, mult;
        struct cpufreq_freqs freqs;
-       static unsigned int old_ratio=-1;
        unsigned long flags;
        unsigned int pic1_mask, pic2_mask;
+       u16 bm_status = 0;
+       u32 bm_timeout = 1000;
+       unsigned int dir = 0;
 
-       if (old_ratio == clock_ratio_index)
-               return;
-       old_ratio = clock_ratio_index;
-
-       mult = clock_ratio[clock_ratio_index];
+       clock_ratio_index = longhaul_table[table_index].index;
+       /* Safety precautions */
+       mult = clock_ratio[clock_ratio_index & 0x1f];
        if (mult == -1)
                return;
-
        speed = calc_speed(mult);
        if ((speed > highest_speed) || (speed < lowest_speed))
                return;
+       /* Voltage transition before frequency transition? */
+       if (can_scale_voltage && longhaul_index < table_index)
+               dir = 1;
 
        freqs.old = calc_speed(longhaul_get_cpu_mult());
        freqs.new = speed;
@@ -285,11 +281,24 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
        outb(0xFF,0xA1);        /* Overkill */
        outb(0xFE,0x21);        /* TMR0 only */
 
+       /* Wait while PCI bus is busy. */
+       if (acpi_regs_addr && (longhaul_flags & USE_NORTHBRIDGE
+           || ((pr != NULL) && pr->flags.bm_control))) {
+               bm_status = inw(acpi_regs_addr);
+               bm_status &= 1 << 4;
+               while (bm_status && bm_timeout) {
+                       outw(1 << 4, acpi_regs_addr);
+                       bm_timeout--;
+                       bm_status = inw(acpi_regs_addr);
+                       bm_status &= 1 << 4;
+               }
+       }
+
        if (longhaul_flags & USE_NORTHBRIDGE) {
                /* Disable AGP and PCI arbiters */
                outb(3, 0x22);
        } else if ((pr != NULL) && pr->flags.bm_control) {
-               /* Disable bus master arbitration */
+               /* Disable bus master arbitration */
                acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
        }
        switch (longhaul_version) {
@@ -314,9 +323,9 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
                if (longhaul_flags & USE_ACPI_C3) {
                        /* Don't allow wakeup */
                        acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
-                       do_powersaver(cx->address, clock_ratio_index);
+                       do_powersaver(cx->address, clock_ratio_index, dir);
                } else {
-                       do_powersaver(0, clock_ratio_index);
+                       do_powersaver(0, clock_ratio_index, dir);
                }
                break;
        }
@@ -336,6 +345,9 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
 
        freqs.new = calc_speed(longhaul_get_cpu_mult());
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+       if (!bm_timeout)
+               printk(KERN_INFO PFX "Warning: Timeout while waiting for idle PCI bus.\n");
 }
 
 /*
@@ -369,7 +381,8 @@ static int guess_fsb(int mult)
 
 static int __init longhaul_get_ranges(void)
 {
-       unsigned int j, k = 0;
+       unsigned int i, j, k = 0;
+       unsigned int ratio;
        int mult;
 
        /* Get current frequency */
@@ -423,8 +436,7 @@ static int __init longhaul_get_ranges(void)
        if(!longhaul_table)
                return -ENOMEM;
 
-       for (j=0; j < numscales; j++) {
-               unsigned int ratio;
+       for (j = 0; j < numscales; j++) {
                ratio = clock_ratio[j];
                if (ratio == -1)
                        continue;
@@ -434,13 +446,41 @@ static int __init longhaul_get_ranges(void)
                longhaul_table[k].index = j;
                k++;
        }
+       if (k <= 1) {
+               kfree(longhaul_table);
+               return -ENODEV;
+       }
+       /* Sort */
+       for (j = 0; j < k - 1; j++) {
+               unsigned int min_f, min_i;
+               min_f = longhaul_table[j].frequency;
+               min_i = j;
+               for (i = j + 1; i < k; i++) {
+                       if (longhaul_table[i].frequency < min_f) {
+                               min_f = longhaul_table[i].frequency;
+                               min_i = i;
+                       }
+               }
+               if (min_i != j) {
+                       unsigned int temp;
+                       temp = longhaul_table[j].frequency;
+                       longhaul_table[j].frequency = longhaul_table[min_i].frequency;
+                       longhaul_table[min_i].frequency = temp;
+                       temp = longhaul_table[j].index;
+                       longhaul_table[j].index = longhaul_table[min_i].index;
+                       longhaul_table[min_i].index = temp;
+               }
+       }
 
        longhaul_table[k].frequency = CPUFREQ_TABLE_END;
-       if (!k) {
-               kfree (longhaul_table);
-               return -EINVAL;
-       }
 
+       /* Find index we are running on */
+       for (j = 0; j < k; j++) {
+               if (clock_ratio[longhaul_table[j].index & 0x1f] == mult) {
+                       longhaul_index = j;
+                       break;
+               }
+       }
        return 0;
 }
 
@@ -448,7 +488,7 @@ static int __init longhaul_get_ranges(void)
 static void __init longhaul_setup_voltagescaling(void)
 {
        union msr_longhaul longhaul;
-       struct mV_pos minvid, maxvid;
+       struct mV_pos minvid, maxvid, vid;
        unsigned int j, speed, pos, kHz_step, numvscales;
        int min_vid_speed;
 
@@ -459,11 +499,11 @@ static void __init longhaul_setup_voltagescaling(void)
        }
 
        if (!longhaul.bits.VRMRev) {
-               printk (KERN_INFO PFX "VRM 8.5\n");
+               printk(KERN_INFO PFX "VRM 8.5\n");
                vrm_mV_table = &vrm85_mV[0];
                mV_vrm_table = &mV_vrm85[0];
        } else {
-               printk (KERN_INFO PFX "Mobile VRM\n");
+               printk(KERN_INFO PFX "Mobile VRM\n");
                if (cpu_model < CPU_NEHEMIAH)
                        return;
                vrm_mV_table = &mobilevrm_mV[0];
@@ -523,7 +563,6 @@ static void __init longhaul_setup_voltagescaling(void)
        /* Calculate kHz for one voltage step */
        kHz_step = (highest_speed - min_vid_speed) / numvscales;
 
-
        j = 0;
        while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
                speed = longhaul_table[j].frequency;
@@ -531,15 +570,14 @@ static void __init longhaul_setup_voltagescaling(void)
                        pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
                else
                        pos = minvid.pos;
-               f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos];
-               f_msr_table[longhaul_table[j].index].pos = pos;
+               longhaul_table[j].index |= mV_vrm_table[pos] << 8;
+               vid = vrm_mV_table[mV_vrm_table[pos]];
+               printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n", speed, j, vid.mV);
                j++;
        }
 
-       longhaul_pos = maxvid.pos;
        can_scale_voltage = 1;
-       printk(KERN_INFO PFX "Voltage scaling enabled. "
-               "Use of \"conservative\" governor is highly recommended.\n");
+       printk(KERN_INFO PFX "Voltage scaling enabled.\n");
 }
 
 
@@ -553,15 +591,44 @@ static int longhaul_target(struct cpufreq_policy *policy,
                            unsigned int target_freq, unsigned int relation)
 {
        unsigned int table_index = 0;
-       unsigned int new_clock_ratio = 0;
+       unsigned int i;
+       unsigned int dir = 0;
+       u8 vid, current_vid;
 
        if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index))
                return -EINVAL;
 
-       new_clock_ratio = longhaul_table[table_index].index & 0xFF;
-
-       longhaul_setstate(new_clock_ratio);
+       /* Don't set same frequency again */
+       if (longhaul_index == table_index)
+               return 0;
 
+       if (!can_scale_voltage)
+               longhaul_setstate(table_index);
+       else {
+               /* On test system voltage transitions exceeding single
+                * step up or down were turning motherboard off. Both
+                * "ondemand" and "userspace" are unsafe. C7 is doing
+                * this in hardware, C3 is old and we need to do this
+                * in software. */
+               i = longhaul_index;
+               current_vid = (longhaul_table[longhaul_index].index >> 8) & 0x1f;
+               if (table_index > longhaul_index)
+                       dir = 1;
+               while (i != table_index) {
+                       vid = (longhaul_table[i].index >> 8) & 0x1f;
+                       if (vid != current_vid) {
+                               longhaul_setstate(i);
+                               current_vid = vid;
+                               msleep(200);
+                       }
+                       if (dir)
+                               i++;
+                       else
+                               i--;
+               }
+               longhaul_setstate(table_index);
+       }
+       longhaul_index = table_index;
        return 0;
 }
 
@@ -590,11 +657,10 @@ static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
 static int enable_arbiter_disable(void)
 {
        struct pci_dev *dev;
-       int status;
+       int status = 1;
        int reg;
        u8 pci_cmd;
 
-       status = 1;
        /* Find PLE133 host bridge */
        reg = 0x78;
        dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0,
@@ -627,13 +693,17 @@ static int enable_arbiter_disable(void)
        return 0;
 }
 
-static int longhaul_setup_vt8235(void)
+static int longhaul_setup_southbridge(void)
 {
        struct pci_dev *dev;
        u8 pci_cmd;
 
        /* Find VT8235 southbridge */
        dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
+       if (dev == NULL)
+       /* Find VT8237 southbridge */
+               dev = pci_get_device(PCI_VENDOR_ID_VIA,
+                                    PCI_DEVICE_ID_VIA_8237, NULL);
        if (dev != NULL) {
                /* Set transition time to max */
                pci_read_config_byte(dev, 0xec, &pci_cmd);
@@ -645,6 +715,14 @@ static int longhaul_setup_vt8235(void)
                pci_read_config_byte(dev, 0xe5, &pci_cmd);
                pci_cmd |= 1 << 7;
                pci_write_config_byte(dev, 0xe5, pci_cmd);
+               /* Get address of ACPI registers block*/
+               pci_read_config_byte(dev, 0x81, &pci_cmd);
+               if (pci_cmd & 1 << 7) {
+                       pci_read_config_dword(dev, 0x88, &acpi_regs_addr);
+                       acpi_regs_addr &= 0xff00;
+                       printk(KERN_INFO PFX "ACPI I/O at 0x%x\n", acpi_regs_addr);
+               }
+
                pci_dev_put(dev);
                return 1;
        }
@@ -657,7 +735,6 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
        char *cpuname=NULL;
        int ret;
        u32 lo, hi;
-       int vt8235_present;
 
        /* Check what we have on this motherboard */
        switch (c->x86_model) {
@@ -755,7 +832,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
        };
 
        /* Doesn't hurt */
-       vt8235_present = longhaul_setup_vt8235();
+       longhaul_setup_southbridge();
 
        /* Find ACPI data for processor */
        acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
@@ -765,35 +842,29 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
        /* Check ACPI support for C3 state */
        if (pr != NULL && longhaul_version == TYPE_POWERSAVER) {
                cx = &pr->power.states[ACPI_STATE_C3];
-               if (cx->address > 0 && cx->latency <= 1000) {
+               if (cx->address > 0 && cx->latency <= 1000)
                        longhaul_flags |= USE_ACPI_C3;
-                       goto print_support_type;
-               }
        }
+       /* Disable if it isn't working */
+       if (disable_acpi_c3)
+               longhaul_flags &= ~USE_ACPI_C3;
        /* Check if northbridge is friendly */
-       if (enable_arbiter_disable()) {
+       if (enable_arbiter_disable())
                longhaul_flags |= USE_NORTHBRIDGE;
-               goto print_support_type;
-       }
-       /* Use VT8235 southbridge if present */
-       if (longhaul_version == TYPE_POWERSAVER && vt8235_present) {
-               longhaul_flags |= USE_VT8235;
-               goto print_support_type;
-       }
+
        /* Check ACPI support for bus master arbiter disable */
-       if ((pr == NULL) || !(pr->flags.bm_control)) {
+       if (!(longhaul_flags & USE_ACPI_C3
+            || longhaul_flags & USE_NORTHBRIDGE)
+           && ((pr == NULL) || !(pr->flags.bm_control))) {
                printk(KERN_ERR PFX
                        "No ACPI support. Unsupported northbridge.\n");
                return -ENODEV;
        }
 
-print_support_type:
        if (longhaul_flags & USE_NORTHBRIDGE)
-               printk (KERN_INFO PFX "Using northbridge support.\n");
-       else if (longhaul_flags & USE_VT8235)
-               printk (KERN_INFO PFX "Using VT8235 support.\n");
-       else
-               printk (KERN_INFO PFX "Using ACPI support.\n");
+               printk(KERN_INFO PFX "Using northbridge support.\n");
+       if (longhaul_flags & USE_ACPI_C3)
+               printk(KERN_INFO PFX "Using ACPI support.\n");
 
        ret = longhaul_get_ranges();
        if (ret != 0)
@@ -885,6 +956,9 @@ static void __exit longhaul_exit(void)
        kfree(longhaul_table);
 }
 
+module_param (disable_acpi_c3, int, 0644);
+MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
+
 module_param (scale_voltage, int, 0644);
 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
 
index 102548f128422ffba612cbc7d9ed5efe949f3cd0..4fcc320997dfd5b9462d21f9282ca2bdcb0c85f0 100644 (file)
@@ -180,7 +180,7 @@ static const int __initdata ezrat_clock_ratio[32] = {
 
        -1,  /* 0000 -> RESERVED (10.0x) */
        110, /* 0001 -> 11.0x */
-       120, /* 0010 -> 12.0x */
+       -1, /* 0010 -> 12.0x */
        -1,  /* 0011 -> RESERVED (9.0x)*/
        105, /* 0100 -> 10.5x */
        115, /* 0101 -> 11.5x */
@@ -237,7 +237,7 @@ static const int __initdata ezrat_eblcr[32] = {
 
 static const int __initdata  nehemiah_clock_ratio[32] = {
        100, /* 0000 -> 10.0x */
-       160, /* 0001 -> 16.0x */
+       -1, /* 0001 -> 16.0x */
        40,  /* 0010 ->  4.0x */
        90,  /* 0011 ->  9.0x */
        95,  /* 0100 ->  9.5x */
@@ -252,10 +252,10 @@ static const int __initdata  nehemiah_clock_ratio[32] = {
        75,  /* 1101 ->  7.5x */
        85,  /* 1110 ->  8.5x */
        120, /* 1111 -> 12.0x */
-       100, /* 0000 -> 10.0x */
+       -1, /* 0000 -> 10.0x */
        110, /* 0001 -> 11.0x */
-       120, /* 0010 -> 12.0x */
-       90,  /* 0011 ->  9.0x */
+       -1, /* 0010 -> 12.0x */
+       -1,  /* 0011 ->  9.0x */
        105, /* 0100 -> 10.5x */
        115, /* 0101 -> 11.5x */
        125, /* 0110 -> 12.5x */
@@ -267,7 +267,7 @@ static const int __initdata  nehemiah_clock_ratio[32] = {
        145, /* 1100 -> 14.5x */
        155, /* 1101 -> 15.5x */
        -1,  /* 1110 -> RESERVED (13.0x) */
-       120, /* 1111 -> 12.0x */
+       -1, /* 1111 -> 12.0x */
 };
 
 static const int __initdata nehemiah_eblcr[32] = {
index 4ade55c5f33377eb5a5a89c82fc4b6648022aff6..34ed53a067307d78166019961f5e431c26f83c1f 100644 (file)
@@ -599,14 +599,17 @@ static void print_basics(struct powernow_k8_data *data)
        for (j = 0; j < data->numps; j++) {
                if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) {
                        if (cpu_family == CPU_HW_PSTATE) {
-                       printk(KERN_INFO PFX "   %d : fid 0x%x gid 0x%x (%d MHz)\n", j, (data->powernow_table[j].index & 0xff00) >> 8,
-                               (data->powernow_table[j].index & 0xff0000) >> 16,
-                               data->powernow_table[j].frequency/1000);
+                               printk(KERN_INFO PFX "   %d : fid 0x%x did 0x%x (%d MHz)\n",
+                                       j,
+                                       (data->powernow_table[j].index & 0xff00) >> 8,
+                                       (data->powernow_table[j].index & 0xff0000) >> 16,
+                                       data->powernow_table[j].frequency/1000);
                        } else {
-                       printk(KERN_INFO PFX "   %d : fid 0x%x (%d MHz), vid 0x%x\n", j,
-                               data->powernow_table[j].index & 0xff,
-                               data->powernow_table[j].frequency/1000,
-                               data->powernow_table[j].index >> 8);
+                               printk(KERN_INFO PFX "   %d : fid 0x%x (%d MHz), vid 0x%x\n",
+                                       j,
+                                       data->powernow_table[j].index & 0xff,
+                                       data->powernow_table[j].frequency/1000,
+                                       data->powernow_table[j].index >> 8);
                        }
                }
        }
@@ -1086,7 +1089,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
 
        if (cpu_family == CPU_HW_PSTATE)
                dprintk("targ: curr fid 0x%x, did 0x%x\n",
-                       data->currfid, data->currvid);
+                       data->currfid, data->currdid);
        else {
                dprintk("targ: curr fid 0x%x, vid 0x%x\n",
                data->currfid, data->currvid);
@@ -1322,16 +1325,22 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
 static int __cpuinit powernowk8_init(void)
 {
        unsigned int i, supported_cpus = 0;
+       unsigned int booted_cores = 1;
 
        for_each_online_cpu(i) {
                if (check_supported_cpu(i))
                        supported_cpus++;
        }
 
+#ifdef CONFIG_SMP
+       booted_cores = cpu_data[0].booted_cores;
+#endif
+
        if (supported_cpus == num_online_cpus()) {
                printk(KERN_INFO PFX "Found %d %s "
-                       "processors (" VERSION ")\n", supported_cpus,
-                       boot_cpu_data.x86_model_id);
+                       "processors (%d cpu cores) (" VERSION ")\n",
+                       supported_cpus/booted_cores,
+                       boot_cpu_data.x86_model_id, supported_cpus);
                return cpufreq_register_driver(&cpufreq_amd64_driver);
        }
 
index 35489fd68852306a14f3e8235857f0d85a08107d..6c5dc2c85aeb99241ef85fac0cd20bfcc1e522a2 100644 (file)
 #include <linux/delay.h>
 #include <linux/compiler.h>
 
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-#include <linux/acpi.h>
-#include <linux/dmi.h>
-#include <acpi/processor.h>
-#endif
-
 #include <asm/msr.h>
 #include <asm/processor.h>
 #include <asm/cpufeature.h>
@@ -257,9 +251,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
                /* Matched a non-match */
                dprintk("no table support for CPU model \"%s\"\n",
                       cpu->x86_model_id);
-#ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-               dprintk("try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
-#endif
+               dprintk("try using the acpi-cpufreq driver\n");
                return -ENOENT;
        }
 
@@ -346,213 +338,6 @@ static unsigned int get_cur_freq(unsigned int cpu)
 }
 
 
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-
-static struct acpi_processor_performance *acpi_perf_data[NR_CPUS];
-
-/*
- * centrino_cpu_early_init_acpi - Do the preregistering with ACPI P-States
- * library
- *
- * Before doing the actual init, we need to do _PSD related setup whenever
- * supported by the BIOS. These are handled by this early_init routine.
- */
-static int centrino_cpu_early_init_acpi(void)
-{
-       unsigned int    i, j;
-       struct acpi_processor_performance       *data;
-
-       for_each_possible_cpu(i) {
-               data = kzalloc(sizeof(struct acpi_processor_performance), 
-                               GFP_KERNEL);
-               if (!data) {
-                       for_each_possible_cpu(j) {
-                               kfree(acpi_perf_data[j]);
-                               acpi_perf_data[j] = NULL;
-                       }
-                       return (-ENOMEM);
-               }
-               acpi_perf_data[i] = data;
-       }
-
-       acpi_processor_preregister_performance(acpi_perf_data);
-       return 0;
-}
-
-
-#ifdef CONFIG_SMP
-/*
- * Some BIOSes do SW_ANY coordination internally, either set it up in hw
- * or do it in BIOS firmware and won't inform about it to OS. If not
- * detected, this has a side effect of making CPU run at a different speed
- * than OS intended it to run at. Detect it and handle it cleanly.
- */
-static int bios_with_sw_any_bug;
-static int sw_any_bug_found(struct dmi_system_id *d)
-{
-       bios_with_sw_any_bug = 1;
-       return 0;
-}
-
-static struct dmi_system_id sw_any_bug_dmi_table[] = {
-       {
-               .callback = sw_any_bug_found,
-               .ident = "Supermicro Server X6DLP",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "080010"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"),
-               },
-       },
-       { }
-};
-#endif
-
-/*
- * centrino_cpu_init_acpi - register with ACPI P-States library
- *
- * Register with the ACPI P-States library (part of drivers/acpi/processor.c)
- * in order to determine correct frequency and voltage pairings by reading
- * the _PSS of the ACPI DSDT or SSDT tables.
- */
-static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
-{
-       unsigned long                   cur_freq;
-       int                             result = 0, i;
-       unsigned int                    cpu = policy->cpu;
-       struct acpi_processor_performance       *p;
-
-       p = acpi_perf_data[cpu];
-
-       /* register with ACPI core */
-       if (acpi_processor_register_performance(p, cpu)) {
-               dprintk(PFX "obtaining ACPI data failed\n");
-               return -EIO;
-       }
-
-       policy->shared_type = p->shared_type;
-       /*
-        * Will let policy->cpus know about dependency only when software 
-        * coordination is required.
-        */
-       if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
-           policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
-               policy->cpus = p->shared_cpu_map;
-       }
-
-#ifdef CONFIG_SMP
-       dmi_check_system(sw_any_bug_dmi_table);
-       if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
-               policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
-               policy->cpus = cpu_core_map[cpu];
-       }
-#endif
-
-       /* verify the acpi_data */
-       if (p->state_count <= 1) {
-               dprintk("No P-States\n");
-               result = -ENODEV;
-               goto err_unreg;
-       }
-
-       if ((p->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
-           (p->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
-               dprintk("Invalid control/status registers (%x - %x)\n",
-                       p->control_register.space_id, p->status_register.space_id);
-               result = -EIO;
-               goto err_unreg;
-       }
-
-       for (i=0; i<p->state_count; i++) {
-               if ((p->states[i].control & INTEL_MSR_RANGE) !=
-                   (p->states[i].status & INTEL_MSR_RANGE)) {
-                       dprintk("Different MSR bits in control (%llu) and status (%llu)\n",
-                               p->states[i].control, p->states[i].status);
-                       result = -EINVAL;
-                       goto err_unreg;
-               }
-
-               if (!p->states[i].core_frequency) {
-                       dprintk("Zero core frequency for state %u\n", i);
-                       result = -EINVAL;
-                       goto err_unreg;
-               }
-
-               if (p->states[i].core_frequency > p->states[0].core_frequency) {
-                       dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i,
-                               p->states[i].core_frequency, p->states[0].core_frequency);
-                       p->states[i].core_frequency = 0;
-                       continue;
-               }
-       }
-
-       centrino_model[cpu] = kzalloc(sizeof(struct cpu_model), GFP_KERNEL);
-       if (!centrino_model[cpu]) {
-               result = -ENOMEM;
-               goto err_unreg;
-       }
-
-       centrino_model[cpu]->model_name=NULL;
-       centrino_model[cpu]->max_freq = p->states[0].core_frequency * 1000;
-       centrino_model[cpu]->op_points =  kmalloc(sizeof(struct cpufreq_frequency_table) *
-                                            (p->state_count + 1), GFP_KERNEL);
-        if (!centrino_model[cpu]->op_points) {
-                result = -ENOMEM;
-                goto err_kfree;
-        }
-
-        for (i=0; i<p->state_count; i++) {
-               centrino_model[cpu]->op_points[i].index = p->states[i].control & INTEL_MSR_RANGE;
-               centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000;
-               dprintk("adding state %i with frequency %u and control value %04x\n", 
-                       i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index);
-       }
-       centrino_model[cpu]->op_points[p->state_count].frequency = CPUFREQ_TABLE_END;
-
-       cur_freq = get_cur_freq(cpu);
-
-       for (i=0; i<p->state_count; i++) {
-               if (!p->states[i].core_frequency) {
-                       dprintk("skipping state %u\n", i);
-                       centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID;
-                       continue;
-               }
-               
-               if (extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0) !=
-                   (centrino_model[cpu]->op_points[i].frequency)) {
-                       dprintk("Invalid encoded frequency (%u vs. %u)\n",
-                               extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0),
-                               centrino_model[cpu]->op_points[i].frequency);
-                       result = -EINVAL;
-                       goto err_kfree_all;
-               }
-
-               if (cur_freq == centrino_model[cpu]->op_points[i].frequency)
-                       p->state = i;
-       }
-
-       /* notify BIOS that we exist */
-       acpi_processor_notify_smm(THIS_MODULE);
-       printk("speedstep-centrino with X86_SPEEDSTEP_CENTRINO_ACPI "
-              "config is deprecated.\n "
-              "Use X86_ACPI_CPUFREQ (acpi-cpufreq) instead.\n" );
-
-       return 0;
-
- err_kfree_all:
-       kfree(centrino_model[cpu]->op_points);
- err_kfree:
-       kfree(centrino_model[cpu]);
- err_unreg:
-       acpi_processor_unregister_performance(p, cpu);
-       dprintk(PFX "invalid ACPI data\n");
-       return (result);
-}
-#else
-static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; }
-static inline int centrino_cpu_early_init_acpi(void) { return 0; }
-#endif
-
 static int centrino_cpu_init(struct cpufreq_policy *policy)
 {
        struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
@@ -568,27 +353,25 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
        if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC))
                centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
 
-       if (centrino_cpu_init_acpi(policy)) {
-               if (policy->cpu != 0)
-                       return -ENODEV;
+       if (policy->cpu != 0)
+               return -ENODEV;
 
-               for (i = 0; i < N_IDS; i++)
-                       if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
-                               break;
+       for (i = 0; i < N_IDS; i++)
+               if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
+                       break;
 
-               if (i != N_IDS)
-                       centrino_cpu[policy->cpu] = &cpu_ids[i];
+       if (i != N_IDS)
+               centrino_cpu[policy->cpu] = &cpu_ids[i];
 
-               if (!centrino_cpu[policy->cpu]) {
-                       dprintk("found unsupported CPU with "
-                       "Enhanced SpeedStep: send /proc/cpuinfo to "
-                       MAINTAINER "\n");
-                       return -ENODEV;
-               }
+       if (!centrino_cpu[policy->cpu]) {
+               dprintk("found unsupported CPU with "
+               "Enhanced SpeedStep: send /proc/cpuinfo to "
+               MAINTAINER "\n");
+               return -ENODEV;
+       }
 
-               if (centrino_cpu_init_table(policy)) {
-                       return -ENODEV;
-               }
+       if (centrino_cpu_init_table(policy)) {
+               return -ENODEV;
        }
 
        /* Check to see if Enhanced SpeedStep is enabled, and try to
@@ -634,20 +417,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
 
        cpufreq_frequency_table_put_attr(cpu);
 
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-       if (!centrino_model[cpu]->model_name) {
-               static struct acpi_processor_performance *p;
-
-               if (acpi_perf_data[cpu]) {
-                       p = acpi_perf_data[cpu];
-                       dprintk("unregistering and freeing ACPI data\n");
-                       acpi_processor_unregister_performance(p, cpu);
-                       kfree(centrino_model[cpu]->op_points);
-                       kfree(centrino_model[cpu]);
-               }
-       }
-#endif
-
        centrino_model[cpu] = NULL;
 
        return 0;
@@ -849,25 +618,12 @@ static int __init centrino_init(void)
        if (!cpu_has(cpu, X86_FEATURE_EST))
                return -ENODEV;
 
-       centrino_cpu_early_init_acpi();
-
        return cpufreq_register_driver(&centrino_driver);
 }
 
 static void __exit centrino_exit(void)
 {
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-       unsigned int j;
-#endif
-       
        cpufreq_unregister_driver(&centrino_driver);
-
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-       for_each_possible_cpu(j) {
-               kfree(acpi_perf_data[j]);
-               acpi_perf_data[j] = NULL;
-       }
-#endif
 }
 
 MODULE_AUTHOR ("Jeremy Fitzhardinge <jeremy@goop.org>");
index 698f980eb4438855ced62e38d3030d4f354e0290..a5b2346faf1fd2bba8d01bcbedb2253f4d3529cb 100644 (file)
@@ -205,7 +205,6 @@ static unsigned int speedstep_detect_chipset (void)
                 * host brige. Abort on these systems.
                 */
                static struct pci_dev *hostbridge;
-               u8 rev = 0;
 
                hostbridge  = pci_get_subsys(PCI_VENDOR_ID_INTEL,
                              PCI_DEVICE_ID_INTEL_82815_MC,
@@ -216,8 +215,7 @@ static unsigned int speedstep_detect_chipset (void)
                if (!hostbridge)
                        return 2; /* 2-M */
 
-               pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev);
-               if (rev < 5) {
+               if (hostbridge->revision < 5) {
                        dprintk("hostbridge does not support speedstep\n");
                        speedstep_chipset_dev = NULL;
                        pci_dev_put(hostbridge);
index 89d91e6cc97213849d87db7f537e0798a4fb968e..1e31b6caffb1651def36e96acf4cd06e4df48d4e 100644 (file)
@@ -29,7 +29,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
-               NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow",
+               NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm",
+               "3dnowext", "3dnow",
 
                /* Transmeta-defined */
                "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -40,8 +41,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                /* Other (Linux-defined) */
                "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
                NULL, NULL, NULL, NULL,
-               "constant_tsc", "up", NULL, NULL, NULL, NULL, NULL, NULL,
-               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               "constant_tsc", "up", NULL, "arch_perfmon",
+               "pebs", "bts", NULL, "sync_rdtsc",
+               "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* Intel-defined (#2) */
@@ -57,9 +59,16 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* AMD-defined (#2) */
-               "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8legacy", "abm",
-               "sse4a", "misalignsse",
-               "3dnowprefetch", "osvw", "ibs", NULL, NULL, NULL, NULL, NULL,
+               "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy",
+               "altmovcr8", "abm", "sse4a",
+               "misalignsse", "3dnowprefetch",
+               "osvw", "ibs", NULL, NULL, NULL, NULL,
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+               /* Auxiliary (Linux-defined) */
+               "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
        };
index 9645bb51f76a38c01a8c250d087ee46de44ceb0c..fc822a46897a720de02dd29d9a286c92c8e9e605 100644 (file)
@@ -734,7 +734,7 @@ void __init print_memory_map(char *who)
                case E820_NVS:
                                printk("(ACPI NVS)\n");
                                break;
-               default:        printk("type %lu\n", e820.map[i].type);
+               default:        printk("type %u\n", e820.map[i].type);
                                break;
                }
        }
index 698c24fe482eef9085fd380233b9364333581c14..2d61e65eeb504164318c0c9e0b839b2a52808e2b 100644 (file)
@@ -102,19 +102,10 @@ static unsigned int highmem_pages = -1;
 /*
  * Setup options
  */
-struct drive_info_struct { char dummy[32]; } drive_info;
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \
-    defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
-EXPORT_SYMBOL(drive_info);
-#endif
 struct screen_info screen_info;
 EXPORT_SYMBOL(screen_info);
 struct apm_info apm_info;
 EXPORT_SYMBOL(apm_info);
-struct sys_desc_table_struct {
-       unsigned short length;
-       unsigned char table[0];
-};
 struct edid_info edid_info;
 EXPORT_SYMBOL_GPL(edid_info);
 struct ist_info ist_info;
@@ -134,7 +125,7 @@ unsigned long saved_videomode;
 
 static char __initdata command_line[COMMAND_LINE_SIZE];
 
-unsigned char __initdata boot_params[PARAM_SIZE];
+struct boot_params __initdata boot_params;
 
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
 struct edd edd;
@@ -528,7 +519,6 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
        ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
-       drive_info = DRIVE_INFO;
        screen_info = SCREEN_INFO;
        edid_info = EDID_INFO;
        apm_info.bios = APM_BIOS_INFO;
diff --git a/arch/i386/kernel/verify_cpu.S b/arch/i386/kernel/verify_cpu.S
deleted file mode 100644 (file)
index f1d1eac..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Check if CPU has some minimum CPUID bits
-   This runs in 16bit mode so that the caller can still use the BIOS
-   to output errors on the screen */
-#include <asm/cpufeature.h>
-#include <asm/msr.h>
-
-verify_cpu:
-       pushfl                          # Save caller passed flags
-       pushl   $0                      # Kill any dangerous flags
-       popfl
-
-#if CONFIG_X86_MINIMUM_CPU_MODEL >= 4
-       pushfl
-       pop     %eax
-       orl     $(1<<18),%eax           # try setting AC
-       push    %eax
-       popfl
-       pushfl
-       popl    %eax
-       testl   $(1<<18),%eax
-       jz      bad
-#endif
-#if REQUIRED_MASK1 != 0
-       pushfl                          # standard way to check for cpuid
-       popl    %eax
-       movl    %eax,%ebx
-       xorl    $0x200000,%eax
-       pushl   %eax
-       popfl
-       pushfl
-       popl    %eax
-       cmpl    %eax,%ebx
-       pushfl                          # standard way to check for cpuid
-       popl    %eax
-       movl    %eax,%ebx
-       xorl    $0x200000,%eax
-       pushl   %eax
-       popfl
-       pushfl
-       popl    %eax
-       cmpl    %eax,%ebx
-       jz      bad                     # REQUIRED_MASK1 != 0 requires CPUID
-
-       movl    $0x0,%eax               # See if cpuid 1 is implemented
-       cpuid
-       cmpl    $0x1,%eax
-       jb      bad                     # no cpuid 1
-
-#if REQUIRED_MASK1 & NEED_CMPXCHG64
-       /* Some VIA C3s need magic MSRs to enable CX64. Do this here */
-       cmpl    $0x746e6543,%ebx        # Cent
-       jne     1f
-       cmpl    $0x48727561,%edx        # aurH
-       jne     1f
-       cmpl    $0x736c7561,%ecx        # auls
-       jne     1f
-       movl    $1,%eax                 # check model
-       cpuid
-       movl    %eax,%ebx
-       shr     $8,%ebx
-       andl    $0xf,%ebx
-       cmp     $6,%ebx                 # check family == 6
-       jne     1f
-       shr     $4,%eax
-       andl    $0xf,%eax
-       cmpl    $6,%eax                 # check model >= 6
-       jb      1f
-       # assume models >= 6 all support this MSR
-       movl    $MSR_VIA_FCR,%ecx
-       rdmsr
-       orl     $((1<<1)|(1<<7)),%eax   # enable CMPXCHG64 and PGE
-       wrmsr
-1:
-#endif
-       movl    $0x1,%eax               # Does the cpu have what it takes
-       cpuid
-
-#if CONFIG_X86_MINIMUM_CPU_MODEL > 4
-#error add proper model checking here
-#endif
-
-       andl    $REQUIRED_MASK1,%edx
-       xorl    $REQUIRED_MASK1,%edx
-       jnz     bad
-#endif /* REQUIRED_MASK1 */
-
-       popfl
-       xor     %eax,%eax
-       ret
-
-bad:
-       popfl
-       movl    $1,%eax
-       ret
index 5199bd03254a58b0359f6efc6968db0daa369154..843b67acf43b9e43e194d577c0814b0319502e24 100644 (file)
@@ -23,13 +23,13 @@ static __init void lithium_init(void)
        set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
 
        if ((li_pcia_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
-           (li_pcia_read16(PCI_DEVICE_ID) != PCI_VENDOR_ID_SGI_LITHIUM)) {
+           (li_pcia_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
                printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'A');
                panic("This machine is not SGI Visual Workstation 320/540");
        }
 
        if ((li_pcib_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
-           (li_pcib_read16(PCI_DEVICE_ID) != PCI_VENDOR_ID_SGI_LITHIUM)) {
+           (li_pcib_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
                printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'B');
                panic("This machine is not SGI Visual Workstation 320/540");
        }
index b95b42950ed447d2774fe2aac9e6e66830d91960..e7306dbf6c4273be26008c28cfc0c2fe5a7bc7bd 100644 (file)
@@ -118,12 +118,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci
 static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
 {
        u8 v;
-       u8 revision;
        int where = 0x55;
        int mask = 0x1f; /* clear bits 5, 6, 7 by default */
 
-       pci_read_config_byte(d, PCI_REVISION_ID, &revision);
-
        if (d->device == PCI_DEVICE_ID_VIA_8367_0) {
                /* fix pci bus latency issues resulted by NB bios error
                   it appears on bug free^Wreduced kt266x's bios forces
@@ -133,8 +130,8 @@ static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
                where = 0x95; /* the memory write queue timer register is 
                                different for the KT266x's: 0x95 not 0x55 */
        } else if (d->device == PCI_DEVICE_ID_VIA_8363_0 &&
-                       (revision == VIA_8363_KL133_REVISION_ID || 
-                       revision == VIA_8363_KM133_REVISION_ID)) {
+                       (d->revision == VIA_8363_KL133_REVISION_ID ||
+                       d->revision == VIA_8363_KM133_REVISION_ID)) {
                        mask = 0x3f; /* clear only bits 6 and 7; clearing bit 5
                                        causes screen corruption on the KL133/KM133 */
        }
@@ -142,7 +139,7 @@ static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
        pci_read_config_byte(d, where, &v);
        if (v & ~mask) {
                printk(KERN_WARNING "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
-                       d->device, revision, where, v, mask, v & mask);
+                       d->device, d->revision, where, v, mask, v & mask);
                v &= mask;
                pci_write_config_byte(d, where, v);
        }
index de1bff6599690c89d9f4f290edcb167e70d79b82..db9ddff958416bd8e189cb0006f60a5fd9cbe4ce 100644 (file)
@@ -520,8 +520,10 @@ config PCI
          here unless you are using a simulator without PCI support.
 
 config PCI_DOMAINS
-       bool
-       default PCI
+       def_bool PCI
+
+config PCI_SYSCALL
+       def_bool PCI
 
 source "drivers/pci/pcie/Kconfig"
 
index 3274850cf2722f07726582c3d133f5c14229d475..74b1ccce4e848187f59df741e944d3edf054f444 100644 (file)
@@ -30,6 +30,7 @@
        .previous
 #define BRL_COND_FSYS_BUBBLE_DOWN(pr)                  \
 [1:](pr)brl.cond.sptk 0;                               \
+       ;;                                              \
        .xdata4 ".data.patch.brl_fsys_bubble_down", 1b-.
 
 GLOBAL_ENTRY(__kernel_syscall_via_break)
index 1ead5ea6c5ce71afaf259eb6629abc8f65a0c11e..4b5daa3cc0feab6723764d67a7c221e74e5b3eb3 100644 (file)
@@ -57,6 +57,9 @@
  *
  * 2006-09-15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
  *           Add printing support for MCA/INIT.
+ *
+ * 2007-04-27 Russ Anderson <rja@sgi.com>
+ *           Support multiple cpus going through OS_MCA in the same event.
  */
 #include <linux/types.h>
 #include <linux/init.h>
@@ -96,7 +99,6 @@
 #endif
 
 /* Used by mca_asm.S */
-u32                            ia64_mca_serialize;
 DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */
 DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */
 DEFINE_PER_CPU(u64, ia64_mca_pal_pte);     /* PTE to map PAL code */
@@ -963,11 +965,12 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
                goto no_mod;
        }
 
+       if (r13 != sos->prev_IA64_KR_CURRENT) {
+               msg = "inconsistent previous current and r13";
+               goto no_mod;
+       }
+
        if (!mca_recover_range(ms->pmsa_iip)) {
-               if (r13 != sos->prev_IA64_KR_CURRENT) {
-                       msg = "inconsistent previous current and r13";
-                       goto no_mod;
-               }
                if ((r12 - r13) >= KERNEL_STACK_SIZE) {
                        msg = "inconsistent r12 and r13";
                        goto no_mod;
@@ -1187,6 +1190,13 @@ all_in:
  *     further MCA logging is enabled by clearing logs.
  *     Monarch also has the duty of sending wakeup-IPIs to pull the
  *     slave processors out of rendezvous spinloop.
+ *
+ *     If multiple processors call into OS_MCA, the first will become
+ *     the monarch.  Subsequent cpus will be recorded in the mca_cpu
+ *     bitmask.  After the first monarch has processed its MCA, it
+ *     will wake up the next cpu in the mca_cpu bitmask and then go
+ *     into the rendezvous loop.  When all processors have serviced
+ *     their MCA, the last monarch frees up the rest of the processors.
  */
 void
 ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
@@ -1196,16 +1206,32 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
        struct task_struct *previous_current;
        struct ia64_mca_notify_die nd =
                { .sos = sos, .monarch_cpu = &monarch_cpu };
+       static atomic_t mca_count;
+       static cpumask_t mca_cpu;
 
+       if (atomic_add_return(1, &mca_count) == 1) {
+               monarch_cpu = cpu;
+               sos->monarch = 1;
+       } else {
+               cpu_set(cpu, mca_cpu);
+               sos->monarch = 0;
+       }
        mprintk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d "
                "monarch=%ld\n", sos->proc_state_param, cpu, sos->monarch);
 
        previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
-       monarch_cpu = cpu;
+
        if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0)
                        == NOTIFY_STOP)
                ia64_mca_spin(__FUNCTION__);
-       ia64_wait_for_slaves(cpu, "MCA");
+       if (sos->monarch) {
+               ia64_wait_for_slaves(cpu, "MCA");
+       } else {
+               ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA;
+               while (cpu_isset(cpu, mca_cpu))
+                       cpu_relax();    /* spin until monarch wakes us */
+               ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+        }
 
        /* Wakeup all the processors which are spinning in the rendezvous loop.
         * They will leave SAL, then spin in the OS with interrupts disabled
@@ -1244,6 +1270,26 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
                        == NOTIFY_STOP)
                ia64_mca_spin(__FUNCTION__);
 
+
+       if (atomic_dec_return(&mca_count) > 0) {
+               int i;
+
+               /* wake up the next monarch cpu,
+                * and put this cpu in the rendez loop.
+                */
+               ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA;
+               for_each_online_cpu(i) {
+                       if (cpu_isset(i, mca_cpu)) {
+                               monarch_cpu = i;
+                               cpu_clear(i, mca_cpu);  /* wake next cpu */
+                               while (monarch_cpu != -1)
+                                       cpu_relax();    /* spin until last cpu leaves */
+                               ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+                               set_curr_task(cpu, previous_current);
+                               return;
+                       }
+               }
+       }
        set_curr_task(cpu, previous_current);
        monarch_cpu = -1;
 }
index 8c9c26aa6ae092e130f93a4076025d17a297ab92..0f5965fcdf85133fbf0c455f714dcbea091eea2d 100644 (file)
@@ -133,14 +133,6 @@ ia64_do_tlb_purge:
 //StartMain////////////////////////////////////////////////////////////////////
 
 ia64_os_mca_dispatch:
-       // Serialize all MCA processing
-       mov     r3=1;;
-       LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);;
-ia64_os_mca_spin:
-       xchg4   r4=[r2],r3;;
-       cmp.ne  p6,p0=r4,r0
-(p6)   br ia64_os_mca_spin
-
        mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET    // use the MCA stack
        LOAD_PHYSICAL(p0,r2,1f)                 // return address
        mov r19=1                               // All MCA events are treated as monarch (for now)
@@ -291,10 +283,6 @@ END(ia64_os_mca_virtual_begin)
 
        mov             b0=r12                  // SAL_CHECK return address
 
-       // release lock
-       LOAD_PHYSICAL(p0,r3,ia64_mca_serialize);;
-       st4.rel         [r3]=r0
-
        br              b0
 
 //EndMain//////////////////////////////////////////////////////////////////////
index f2d4900751ba9375dc8a7afa5cec7c1f2573f5d4..3bccb06c8d216cc1439c0f0081e6bacce2668035 100644 (file)
@@ -40,7 +40,11 @@ GLOBAL_ENTRY(mca_handler_bhhook)
        mov     b6=loc1
        ;;
        mov     loc1=rp
-       ssm     psr.i | psr.ic
+       ssm     psr.ic
+       ;;
+       srlz.i
+       ;;
+       ssm     psr.i
        br.call.sptk.many rp=b6         // does not return ...
        ;;
        mov     ar.pfs=loc0
index af73b8dfde282c0c91f84b3f8da062327d18a069..fa40cba433500df6e7288903eeab205ce283f54d 100644 (file)
@@ -513,7 +513,8 @@ copy_thread (int nr, unsigned long clone_flags,
 static void
 do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg)
 {
-       unsigned long mask, sp, nat_bits = 0, ip, ar_rnat, urbs_end, cfm;
+       unsigned long mask, sp, nat_bits = 0, ar_rnat, urbs_end, cfm;
+       unsigned long uninitialized_var(ip);    /* GCC be quiet */
        elf_greg_t *dst = arg;
        struct pt_regs *pt;
        char nat;
index fa4e6d4810f3cc2c1c8e6c74fd431e79fe53a350..1682fc639038e79f64e5a1e1cb96ad846e843035 100644 (file)
@@ -175,7 +175,7 @@ EXPORT_SYMBOL(flush_tlb_range);
 void __devinit
 ia64_tlb_init (void)
 {
-       ia64_ptce_info_t ptce_info;
+       ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */
        unsigned long tr_pgbits;
        long status;
 
index 73696b4a2eed42caafc4d7414f8ae38c6c3a6922..07d0e92742c8ee604585a526668fd0f0baac8d60 100644 (file)
@@ -591,6 +591,9 @@ int
 pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
                     enum pci_mmap_state mmap_state, int write_combine)
 {
+       unsigned long size = vma->vm_end - vma->vm_start;
+       pgprot_t prot;
+
        /*
         * I/O space cannot be accessed via normal processor loads and
         * stores on this platform.
@@ -604,15 +607,24 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
                 */
                return -EINVAL;
 
+       if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
+               return -EINVAL;
+
+       prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
+                                   vma->vm_page_prot);
+
        /*
-        * Leave vm_pgoff as-is, the PCI space address is the physical
-        * address on this platform.
+        * If the user requested WC, the kernel uses UC or WC for this region,
+        * and the chipset supports WC, we can use WC. Otherwise, we have to
+        * use the same attribute the kernel uses.
         */
-       if (write_combine && efi_range_is_wc(vma->vm_start,
-                                            vma->vm_end - vma->vm_start))
+       if (write_combine &&
+           ((pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_UC ||
+            (pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_WC) &&
+           efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
                vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
        else
-               vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+               vma->vm_page_prot = prot;
 
        if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
                             vma->vm_end - vma->vm_start, vma->vm_page_prot))
index c6216f454ffb5ee81d2246bb05361a073ff51268..3c7178f5dce82bad1492cbc006579db7f18ad98e 100644 (file)
@@ -418,7 +418,7 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
        void __iomem *addr;
        struct pcidev_info *pcidev_info = NULL;
        struct sn_irq_info *sn_irq_info = NULL;
-       size_t size;
+       size_t image_size, size;
 
        if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
                panic("%s:  Failure obtaining pcidev_info for %s\n",
@@ -428,17 +428,16 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
        if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
                /*
                 * A valid ROM image exists and has been shadowed by the
-                * PROM. Setup the pci_dev ROM resource to point to
-                * the shadowed copy.
+                * PROM. Setup the pci_dev ROM resource with the address
+                * of the shadowed copy, and the actual length of the ROM image.
                 */
-               size = dev->resource[PCI_ROM_RESOURCE].end -
-                               dev->resource[PCI_ROM_RESOURCE].start;
-               addr =
-                    ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
-                            size);
+               size = pci_resource_len(dev, PCI_ROM_RESOURCE);
+               addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
+                              size);
+               image_size = pci_get_rom_size(addr, size);
                dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
                dev->resource[PCI_ROM_RESOURCE].end =
-                                               (unsigned long) addr + size;
+                                       (unsigned long) addr + image_size - 1;
                dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
        }
        sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
index 6b10e5d284883380a284a1d2616e1aa2ec834fd2..906b93674b7604e236099c42f68cd8228a1876ed 100644 (file)
@@ -259,9 +259,23 @@ sn_io_slot_fixup(struct pci_dev *dev)
                        insert_resource(&ioport_resource, &dev->resource[idx]);
                else
                        insert_resource(&iomem_resource, &dev->resource[idx]);
-               /* If ROM, mark as shadowed in PROM */
-               if (idx == PCI_ROM_RESOURCE)
-                       dev->resource[idx].flags |= IORESOURCE_ROM_BIOS_COPY;
+               /*
+                * If ROM, set the actual ROM image size, and mark as
+                * shadowed in PROM.
+                */
+               if (idx == PCI_ROM_RESOURCE) {
+                       size_t image_size;
+                       void __iomem *rom;
+
+                       rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE),
+                                     size + 1);
+                       image_size = pci_get_rom_size(rom, size + 1);
+                       dev->resource[PCI_ROM_RESOURCE].end =
+                               dev->resource[PCI_ROM_RESOURCE].start +
+                               image_size - 1;
+                       dev->resource[PCI_ROM_RESOURCE].flags |=
+                                                IORESOURCE_ROM_BIOS_COPY;
+               }
        }
        /* Create a pci_window in the pci_controller struct for
         * each device resource.
index 493380b2c05fd1b6756ad9edb711c4992125f5e7..5a289e4de8383eb7f286ed99fe7d0d1c80c36df5 100644 (file)
@@ -369,7 +369,7 @@ static void tio_corelet_reset(nasid_t nasid, int corelet)
 
 static int is_fpga_tio(int nasid, int *bt)
 {
-       u16 ioboard_type;
+       u16 uninitialized_var(ioboard_type);    /* GCC be quiet */
        s64 rc;
 
        rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type);
index b42bfcae6f911108f364473ae7e3d7a7fcf80b26..42485ad50ceb3aeea3de6312ae22785cf0a994f7 100644 (file)
@@ -80,7 +80,7 @@ static int sal_pcibr_error_interrupt(struct pcibus_info *soft)
 u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus)
 {
        s64 rc;
-       u16 ioboard;
+       u16 uninitialized_var(ioboard);         /* GCC be quiet */
        nasid_t nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
 
        rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard);
index a00fabe2e4e04d6a175eca5077081ab41e8fe847..5c863bcd5614e4076d4417e294458e4bbd5cae8f 100644 (file)
@@ -117,9 +117,9 @@ config MACH_JAZZ
        select ARC32
        select ARCH_MAY_HAVE_PC_FDC
        select GENERIC_ISA_DMA
-       select I8253
        select I8259
        select ISA
+       select PCSPEAKER
        select SYS_HAS_CPU_R4X00
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
@@ -347,9 +347,9 @@ config QEMU
        select DMA_COHERENT
        select GENERIC_ISA_DMA
        select HAVE_STD_PC_SERIAL_PORT
-       select I8253
        select I8259
        select ISA
+       select PCSPEAKER
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_SUPPORTS_32BIT_KERNEL
@@ -562,9 +562,9 @@ config SNI_RM
        select HW_HAS_EISA
        select HW_HAS_PCI
        select IRQ_CPU
-       select I8253
        select I8259
        select ISA
+       select PCSPEAKER
        select SWAP_IO_SPACE if CPU_BIG_ENDIAN
        select SYS_HAS_CPU_R4X00
        select SYS_HAS_CPU_R5000
@@ -1404,6 +1404,19 @@ config MIPS_MT_SMTC_INSTANT_REPLAY
          it off), but ensures that IPIs are handled promptly even under
          heavy I/O interrupt load.
 
+config MIPS_MT_SMTC_IM_BACKSTOP
+       bool "Use per-TC register bits as backstop for inhibited IM bits"
+       depends on MIPS_MT_SMTC
+       default y
+       help
+         To support multiple TC microthreads acting as "CPUs" within
+         a VPE, VPE-wide interrupt mask bits must be specially manipulated
+         during interrupt handling. To support legacy drivers and interrupt
+         controller management code, SMTC has a "backstop" to track and
+         if necessary restore the interrupt mask. This has some performance
+         impact on interrupt service overhead. Disable it only if you know
+         what you are doing.
+
 config MIPS_VPE_LOADER_TOM
        bool "Load VPE program into memory hidden from linux"
        depends on MIPS_VPE_LOADER
@@ -1851,7 +1864,7 @@ config MMU
        bool
        default y
 
-config I8253
+config PCSPEAKER
        bool
 
 source "drivers/pcmcia/Kconfig"
index 13fe187f35d67542a1bfa93acf4544d949ee7261..a95b377731965d9070787f3227530e17535306ac 100644 (file)
@@ -100,18 +100,9 @@ void __init plat_mem_setup(void)
         argptr = prom_getcmdline();
         /* default panel */
         /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
-#ifdef CONFIG_MIPS_HYDROGEN3
-         strcat(argptr, " video=au1100fb:panel:Hydrogen_3_NEC_panel_320x240,nohwcursor");
-#endif
     }
 #endif
 
-#ifdef CONFIG_FB_XPERT98
-       if ((argptr = strstr(argptr, "video=")) == NULL) {
-               argptr = prom_getcmdline();
-               strcat(argptr, " video=atyfb:1024x768-8@70");
-       }
-#endif
 
 #if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
        /* au1000 does not support vra, au1500 and au1100 do */
index fa1c62f055156a509e2b6e5aeed75f0d7b67fa70..8fc29982d700bdc68c7a399b8561bfe0d1c4755a 100644 (file)
@@ -203,11 +203,7 @@ wakeup_counter0_set(int ticks)
 /* I haven't found anyone that doesn't use a 12 MHz source clock,
  * but just in case.....
  */
-#ifdef CONFIG_AU1000_SRC_CLK
-#define AU1000_SRC_CLK CONFIG_AU1000_SRC_CLK
-#else
 #define AU1000_SRC_CLK 12000000
-#endif
 
 /*
  * We read the real processor speed from the PLL.  This is important
@@ -247,33 +243,8 @@ unsigned long cal_r4koff(void)
                au_writel (0, SYS_TOYWRITE);
                while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
 
-#if defined(CONFIG_AU1000_USE32K)
-               {
-                       unsigned long start, end, count;
-
-                       start = au_readl(SYS_RTCREAD);
-                       start += 2;
-                       /* wait for the beginning of a new tick
-                       */
-                       while (au_readl(SYS_RTCREAD) < start);
-
-                       /* Start r4k counter.
-                       */
-                       write_c0_count(0);
-
-                       /* Wait 0.5 seconds.
-                       */
-                       end = start + (32768 / trim_divide)/2;
-
-                       while (end > au_readl(SYS_RTCREAD));
-
-                       count = read_c0_count();
-                       cpu_speed = count * 2;
-               }
-#else
                cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) *
                        AU1000_SRC_CLK;
-#endif
        }
        else {
                /* The 32KHz oscillator isn't running, so assume there
index 043302b7fe589d7eabc873d7d5172c05c6473381..eea2092bde8dfe801fb06fac0b4251c108dad153 100644 (file)
@@ -131,14 +131,7 @@ void __init board_setup(void)
        /* The Pb1200 development board uses external MUX for PSC0 to
        support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
        */
-#if defined(CONFIG_AU1XXX_PSC_SPI) && defined(CONFIG_I2C_AU1550)
-       #error I2C and SPI are mutually exclusive. Both are physically connected to PSC0.\
-                       Refer to Pb1200/Db1200 documentation.
-#elif defined( CONFIG_AU1XXX_PSC_SPI )
-       bcsr->resets |= BCSR_RESETS_PCS0MUX;
-       /*Hard Coding Value to enable Temp Sensors [bit 14] Value for SOC Au1200. Pls refer documentation*/
-         bcsr->resets =0x900f;
-#elif defined( CONFIG_I2C_AU1550 )
+#ifdef CONFIG_I2C_AU1550
        bcsr->resets &= (~BCSR_RESETS_PCS0MUX);
 #endif
        au_sync();
index dd04eece9fd3f17ae4d4dcbad89eeca7f3e78e8e..8a0b4ac5283df2c9c0e951db2b3385e3c06e0300 100644 (file)
@@ -241,7 +241,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 #
 CONFIG_ISA=y
 CONFIG_MMU=y
-CONFIG_I8253=y
+CONFIG_PCSPEAKER=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
index 6cca105832ca1ad43517712a157c8e690c521482..703de002e37213eb0cb62dcdec353fb55e272d55 100644 (file)
@@ -221,7 +221,7 @@ CONFIG_DEFAULT_IOSCHED="noop"
 #
 CONFIG_ISA=y
 CONFIG_MMU=y
-CONFIG_I8253=y
+CONFIG_PCSPEAKER=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
index 1a67a85aabbbfed3b7a732557316aac2e4760991..a5dc5cb97aae69d92f70a699761cbed4d78578b9 100644 (file)
@@ -251,7 +251,7 @@ CONFIG_PCI=y
 CONFIG_ISA=y
 # CONFIG_EISA is not set
 CONFIG_MMU=y
-CONFIG_I8253=y
+CONFIG_PCSPEAKER=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
index f1cdb12f79257eb99695b7ec040e5b9819862186..f342d8c887b800729fd5b6f4bb301798c593f7c9 100644 (file)
@@ -592,8 +592,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_RTC is not set
-CONFIG_GEN_RTC=y
-CONFIG_GEN_RTC_X=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
index 961594cb52142bd15734c315b7fb7e46cda903b4..5c8085b6d7ab944d1e0efbcc70ba270eaa2bafe4 100644 (file)
@@ -63,7 +63,7 @@ obj-$(CONFIG_PROC_FS)         += proc.o
 
 obj-$(CONFIG_64BIT)            += cpu-bugs64.o
 
-obj-$(CONFIG_I8253)            += i8253.o
+obj-$(CONFIG_PCSPEAKER)                += pcspeaker.o
 
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
index 76fd3f22c76624363d94b7e4b870d0e798ff282d..6b5df8bfab85d0a97b503ad2ca441ff37d4c21d0 100644 (file)
@@ -22,7 +22,8 @@
  */
 int __compute_return_epc(struct pt_regs *regs)
 {
-       unsigned int *addr, bit, fcr31, dspcontrol;
+       unsigned int __user *addr;
+       unsigned int bit, fcr31, dspcontrol;
        long epc;
        union mips_instruction insn;
 
@@ -33,7 +34,7 @@ int __compute_return_epc(struct pt_regs *regs)
        /*
         * Read the instruction
         */
-       addr = (unsigned int *) epc;
+       addr = (unsigned int __user *) epc;
        if (__get_user(insn.word, addr)) {
                force_sig(SIGSEGV, current);
                return -EFAULT;
index 686249c5c328a34c105e1c50d458b71effa033f7..e29598ae939d21b7d8e7442300a8741ce612f24a 100644 (file)
@@ -84,6 +84,7 @@ FEXPORT(restore_all)                  # restore full frame
        LONG_S  sp, TI_REGS($28)
        jal     deferred_smtc_ipi
        LONG_S  s0, TI_REGS($28)
+#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
 /* Re-arm any temporarily masked interrupts not explicitly "acked" */
        mfc0    v0, CP0_TCSTATUS
        ori     v1, v0, TCSTATUS_IXMT
@@ -110,6 +111,7 @@ FEXPORT(restore_all)                        # restore full frame
        _ehb
        xor     t0, t0, t3
        mtc0    t0, CP0_TCCONTEXT
+#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
 #endif /* CONFIG_MIPS_MT_SMTC */
        .set    noat
        RESTORE_TEMP
index 297bd56c23471facbd75cbb31b460707c5bf13ba..c0f19d638b986c4f5be93b801a90b4e6717c6419 100644 (file)
@@ -243,9 +243,11 @@ NESTED(except_vec_vi_handler, 0, sp)
         */
        mfc0    t1, CP0_STATUS
        and     t0, a0, t1
+#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
        mfc0    t2, CP0_TCCONTEXT
        or      t0, t0, t2
        mtc0    t0, CP0_TCCONTEXT
+#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
        xor     t1, t1, t0
        mtc0    t1, CP0_STATUS
        _ehb
index 06729596812f744581cce609938fee82d36d25cc..d9bfae53c43f92c5a400301bb02bfb3c05bfad92 100644 (file)
        move    $28, a2
        cpu_restore_nonscratch a1
 
-#if (_THREAD_SIZE - 32) < 0x10000
-       PTR_ADDIU       t0, $28, _THREAD_SIZE - 32
-#else
-       PTR_LI          t0, _THREAD_SIZE - 32
-       PTR_ADDU        t0, $28
-#endif
+       PTR_ADDU        t0, $28, _THREAD_SIZE - 32
        set_saved_sp    t0, t1, t2
 #ifdef CONFIG_MIPS_MT_SMTC
        /* Read-modify-writes of Status must be atomic on a VPE */
index 80ea4fa95bd9b121b4b201e65f74e12b29dbb948..37c562c4c8176f3dfe8dd88251ef1899b42b2ccf 100644 (file)
@@ -131,7 +131,7 @@ static void show_stacktrace(struct task_struct *task, struct pt_regs *regs)
        const int field = 2 * sizeof(unsigned long);
        long stackdata;
        int i;
-       unsigned long *sp = (unsigned long *)regs->regs[29];
+       unsigned long __user *sp = (unsigned long __user *)regs->regs[29];
 
        printk("Stack :");
        i = 0;
@@ -187,7 +187,7 @@ void dump_stack(void)
 
 EXPORT_SYMBOL(dump_stack);
 
-void show_code(unsigned int *pc)
+static void show_code(unsigned int __user *pc)
 {
        long i;
 
@@ -305,7 +305,7 @@ void show_registers(struct pt_regs *regs)
        printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
                current->comm, current->pid, current_thread_info(), current);
        show_stacktrace(current, regs);
-       show_code((unsigned int *) regs->cp0_epc);
+       show_code((unsigned int __user *) regs->cp0_epc);
        printk("\n");
 }
 
@@ -373,7 +373,7 @@ asmlinkage void do_be(struct pt_regs *regs)
                action = MIPS_BE_FIXUP;
 
        if (board_be_handler)
-               action = board_be_handler(regs, fixup != 0);
+               action = board_be_handler(regs, fixup != NULL);
 
        switch (action) {
        case MIPS_BE_DISCARD:
@@ -865,7 +865,7 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
                dump_tlb_all();
        }
 
-       show_code((unsigned int *) regs->cp0_epc);
+       show_code((unsigned int __user *) regs->cp0_epc);
 
        /*
         * Some chips may have other causes of machine check (e.g. SB1
index 1a4db7dc77cb2eaf5effb41e38b159a4da52532c..465ff0ec85b9316d151cca44786a92f0b41c85d7 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/mipsregs.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/tlbdebug.h>
 
 static inline const char *msk2str(unsigned int mask)
 {
index 52f87795ecc3db3e2f50d448bc92a43738f644c0..9cee907975ae0f2f305e157d48a5e8c4e5f92669 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/mipsregs.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/tlbdebug.h>
 
 extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */
 
index 2388f7f3ffde9c2bffd45744f9f8adaacfd10048..58d14f4d9349c3f8b9890c56551c02f8f35737d4 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <asm/addrspace.h>
 #include <asm/bug.h>
+#include <asm/cacheflush.h>
 
 #ifndef CKSEG2
 #define CKSEG2 CKSSEG
index d7f05b0abe170c1deba01094ddea2e86da9806c7..17419e11ecad761e2db48990c91997a51b27d2a3 100644 (file)
@@ -205,7 +205,7 @@ static int isBranchInstr(mips_instruction * i)
 static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 {
        mips_instruction ir;
-       void * emulpc, *contpc;
+       unsigned long emulpc, contpc;
        unsigned int cond;
 
        if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
@@ -230,7 +230,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                 * Linux MIPS branch emulator operates on context, updating the
                 * cp0_epc.
                 */
-               emulpc = (void *) (xcp->cp0_epc + 4);   /* Snapshot emulation target */
+               emulpc = xcp->cp0_epc + 4;      /* Snapshot emulation target */
 
                if (__compute_return_epc(xcp)) {
 #ifdef CP1DBG
@@ -244,12 +244,12 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                        return SIGBUS;
                }
                /* __compute_return_epc() will have updated cp0_epc */
-               contpc = (void *)  xcp->cp0_epc;
+               contpc = xcp->cp0_epc;
                /* In order not to confuse ptrace() et al, tweak context */
-               xcp->cp0_epc = (unsigned long) emulpc - 4;
+               xcp->cp0_epc = emulpc - 4;
        } else {
-               emulpc = (void *)  xcp->cp0_epc;
-               contpc = (void *) (xcp->cp0_epc + 4);
+               emulpc = xcp->cp0_epc;
+               contpc = xcp->cp0_epc + 4;
        }
 
       emul:
@@ -427,8 +427,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                                 * instruction
                                 */
                                xcp->cp0_epc += 4;
-                               contpc = (void *)
-                                       (xcp->cp0_epc +
+                               contpc = (xcp->cp0_epc +
                                        (MIPSInst_SIMM(ir) << 2));
 
                                if (get_user(ir,
@@ -462,7 +461,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                                 * Single step the non-cp1
                                 * instruction in the dslot
                                 */
-                               return mips_dsemul(xcp, ir, (unsigned long) contpc);
+                               return mips_dsemul(xcp, ir, contpc);
                        }
                        else {
                                /* branch not taken */
@@ -521,7 +520,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
        }
 
        /* we did it !! */
-       xcp->cp0_epc = (unsigned long) contpc;
+       xcp->cp0_epc = contpc;
        xcp->cp0_cause &= ~CAUSEF_BD;
 
        return 0;
index ea6ba7248489598e7376768abeef38d7a0fce632..653e325849e417d0ca2f9d646f2c850b5ffc8ec0 100644 (file)
@@ -54,8 +54,7 @@ struct emuframe {
 int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
 {
        extern asmlinkage void handle_dsemulret(void);
-       mips_instruction *dsemul_insns;
-       struct emuframe *fr;
+       struct emuframe __user *fr;
        int err;
 
        if (ir == 0) {          /* a nop is easy */
@@ -87,8 +86,8 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
         */
 
        /* Ensure that the two instructions are in the same cache line */
-       dsemul_insns = (mips_instruction *) ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
-       fr = (struct emuframe *) dsemul_insns;
+       fr = (struct emuframe __user *)
+               ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
 
        /* Verify that the stack pointer is not competely insane */
        if (unlikely(!access_ok(VERIFY_WRITE, fr, sizeof(struct emuframe))))
@@ -113,12 +112,13 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
 
 int do_dsemulret(struct pt_regs *xcp)
 {
-       struct emuframe *fr;
+       struct emuframe __user *fr;
        unsigned long epc;
        u32 insn, cookie;
        int err = 0;
 
-       fr = (struct emuframe *) (xcp->cp0_epc - sizeof(mips_instruction));
+       fr = (struct emuframe __user *)
+               (xcp->cp0_epc - sizeof(mips_instruction));
 
        /*
         * If we can't even access the area, something is very wrong, but we'll
index d86b37235cf6d12385496959bad4d88f2eced616..5cbc3509ab528990c187b8ba3805a2ad0b1750cd 100644 (file)
@@ -77,7 +77,7 @@ asmlinkage void plat_irq_dispatch(void)
        irq = irq_ffs(pending);
 
        if (irq > 0)
-               do_IRQ(MIPSCPU_INT_BASE + irq);
+               do_IRQ(MIPS_CPU_IRQ_BASE + irq);
        else
                spurious_interrupt();
 }
index 3643582bdadebcb2bd6038e85da7b9008d8c34d9..60e66906be659089d4b5e07d19f30be8a5c13d64 100644 (file)
@@ -84,7 +84,7 @@ static void __init serial_init(void)
        /* hardware int 4 - the serial int, is CPU int 6
         but poll for now */
        s.irq =  0;
-       s.uartclk = BASE_BAUD * 16;
+       s.uartclk = 1843200;
        s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
        s.iotype = UPIO_PORT;
        s.regshift = 0;
index 874a18e8ac24b4ba2867457c80c2ddf88d3dc029..a0f5a5dca1b20bfbd97b1dbe89587327561e544e 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
-#include <linux/mipsregs.h>
 #include <linux/smp.h>
 #include <linux/timex.h>
 
index f26ede001a0bafc953cca151761fc8bd9982a8a7..c58bd3d036f4528e5f379844932aa1e6f84cb6f1 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the PCI specific kernel interface routines under Linux.
 #
 
-obj-y                          += pci.o pci-dac.o
+obj-y                          += pci.o
 
 #
 # PCI bus host bridge specific code
index 7fc475f7eae586bce8dfa383b789451cd2435dbb..76b4f0ffb1e5f7a276829c19e5903536856e1523 100644 (file)
@@ -58,8 +58,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
 
 static void qube_raq_galileo_fixup(struct pci_dev *dev)
 {
-       unsigned short galileo_id;
-
        if (dev->devfn != PCI_DEVFN(0, 0))
                return;
 
@@ -84,16 +82,14 @@ static void qube_raq_galileo_fixup(struct pci_dev *dev)
         * Therefore we must set the disconnect/retry cycle values to
         * something sensible when using the new Galileo.
         */
-       pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id);
-       galileo_id &= 0xff;     /* mask off class info */
 
-       printk(KERN_INFO "Galileo: revision %u\n", galileo_id);
+       printk(KERN_INFO "Galileo: revision %u\n", dev->revision);
 
 #if 0
-       if (galileo_id >= 0x10) {
+       if (dev->revision >= 0x10) {
                /* New Galileo, assumes PCI stop line to VIA is connected. */
                GT_WRITE(GT_PCI0_TOR_OFS, 0x4020);
-       } else if (galileo_id == 0x1 || galileo_id == 0x2)
+       } else if (dev->revision == 0x1 || dev->revision == 0x2)
 #endif
        {
                signed int timeo;
diff --git a/arch/mips/pci/pci-dac.c b/arch/mips/pci/pci-dac.c
deleted file mode 100644 (file)
index 0f0ea1b..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001, 06  Ralf Baechle <ralf@linux-mips.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-
-#include <linux/types.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-
-#include <dma-coherence.h>
-
-#include <linux/pci.h>
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-       struct page *page, unsigned long offset, int direction)
-{
-       struct device *dev = &pdev->dev;
-
-       BUG_ON(direction == DMA_NONE);
-
-       if (!plat_device_is_coherent(dev)) {
-               unsigned long addr;
-
-               addr = (unsigned long) page_address(page) + offset;
-               dma_cache_wback_inv(addr, PAGE_SIZE);
-       }
-
-       return plat_map_dma_mem_page(dev, page) + offset;
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-       dma64_addr_t dma_addr)
-{
-       return pfn_to_page(plat_dma_addr_to_phys(dma_addr) >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-       dma64_addr_t dma_addr)
-{
-       return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-       dma64_addr_t dma_addr, size_t len, int direction)
-{
-       BUG_ON(direction == PCI_DMA_NONE);
-
-       if (!plat_device_is_coherent(&pdev->dev))
-               dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-       dma64_addr_t dma_addr, size_t len, int direction)
-{
-       BUG_ON(direction == PCI_DMA_NONE);
-
-       if (!plat_device_is_coherent(&pdev->dev))
-               dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
index 8108231f2e20909ed0057a792a4f3265827fac8f..99d8f4fd3ff4956878a925c214c3eb3e9e60832e 100644 (file)
@@ -269,7 +269,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
        }
 
        for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
-               struct pci_dev *dev = pci_dev_b(ln);
+               dev = pci_dev_b(ln);
 
                if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
                        pcibios_fixup_device_resources(dev, bus);
diff --git a/arch/mips/sibyte/swarm/time.c b/arch/mips/sibyte/swarm/time.c
deleted file mode 100644 (file)
index 97c73c7..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*
- * Time routines for the swarm board.  We pass all the hard stuff
- * through to the sb1250 handling code.  Only thing we really keep
- * track of here is what time of day we think it is.  And we don't
- * really even do a good job of that...
- */
-
-
-#include <linux/bcd.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <asm/system.h>
-#include <asm/addrspace.h>
-#include <asm/io.h>
-
-#include <asm/sibyte/sb1250.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_smbus.h>
-
-static unsigned long long sec_bias = 0;
-static unsigned int usec_bias = 0;
-
-/* Xicor 1241 definitions */
-
-/*
- * Register bits
- */
-
-#define X1241REG_SR_BAT        0x80            /* currently on battery power */
-#define X1241REG_SR_RWEL 0x04          /* r/w latch is enabled, can write RTC */
-#define X1241REG_SR_WEL 0x02           /* r/w latch is unlocked, can enable r/w now */
-#define X1241REG_SR_RTCF 0x01          /* clock failed */
-#define X1241REG_BL_BP2 0x80           /* block protect 2 */
-#define X1241REG_BL_BP1 0x40           /* block protect 1 */
-#define X1241REG_BL_BP0 0x20           /* block protect 0 */
-#define X1241REG_BL_WD1        0x10
-#define X1241REG_BL_WD0        0x08
-#define X1241REG_HR_MIL 0x80           /* military time format */
-
-/*
- * Register numbers
- */
-
-#define X1241REG_BL    0x10            /* block protect bits */
-#define X1241REG_INT   0x11            /*  */
-#define X1241REG_SC    0x30            /* Seconds */
-#define X1241REG_MN    0x31            /* Minutes */
-#define X1241REG_HR    0x32            /* Hours */
-#define X1241REG_DT    0x33            /* Day of month */
-#define X1241REG_MO    0x34            /* Month */
-#define X1241REG_YR    0x35            /* Year */
-#define X1241REG_DW    0x36            /* Day of Week */
-#define X1241REG_Y2K   0x37            /* Year 2K */
-#define X1241REG_SR    0x3F            /* Status register */
-
-#define X1241_CCR_ADDRESS      0x6F
-
-#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg)))
-
-static int xicor_read(uint8_t addr)
-{
-        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-       __raw_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
-       __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_DATA));
-       __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
-                    SMB_CSR(R_SMB_START));
-
-        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-       __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
-                    SMB_CSR(R_SMB_START));
-
-        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-        if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
-                /* Clear error bit by writing a 1 */
-                __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
-                return -1;
-        }
-
-       return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
-}
-
-static int xicor_write(uint8_t addr, int b)
-{
-        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-       __raw_writeq(addr, SMB_CSR(R_SMB_CMD));
-       __raw_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
-       __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
-                    SMB_CSR(R_SMB_START));
-
-        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-        if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
-                /* Clear error bit by writing a 1 */
-                __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
-                return -1;
-        } else {
-               return 0;
-       }
-}
-
-/*
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be
- * called 500 ms after the second nowtime has started, because when
- * nowtime is written into the registers of the CMOS clock, it will
- * jump to the next second precisely 500 ms later. Check the Motorola
- * MC146818A or Dallas DS12887 data sheet for details.
- *
- * BUG: This routine does not handle hour overflow properly; it just
- *      sets the minutes. Usually you'll only notice that after reboot!
- */
-int set_rtc_mmss(unsigned long nowtime)
-{
-       int retval = 0;
-       int real_seconds, real_minutes, cmos_minutes;
-
-       cmos_minutes = xicor_read(X1241REG_MN);
-       cmos_minutes = BCD2BIN(cmos_minutes);
-
-       /*
-        * since we're only adjusting minutes and seconds,
-        * don't interfere with hour overflow. This avoids
-        * messing with unknown time zones but requires your
-        * RTC not to be off by more than 15 minutes
-        */
-       real_seconds = nowtime % 60;
-       real_minutes = nowtime / 60;
-       if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
-               real_minutes += 30;             /* correct for half hour time zone */
-       real_minutes %= 60;
-
-       /* unlock writes to the CCR */
-       xicor_write(X1241REG_SR, X1241REG_SR_WEL);
-       xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
-
-       if (abs(real_minutes - cmos_minutes) < 30) {
-               real_seconds = BIN2BCD(real_seconds);
-               real_minutes = BIN2BCD(real_minutes);
-               xicor_write(X1241REG_SC, real_seconds);
-               xicor_write(X1241REG_MN, real_minutes);
-       } else {
-               printk(KERN_WARNING
-                      "set_rtc_mmss: can't update from %d to %d\n",
-                      cmos_minutes, real_minutes);
-               retval = -1;
-       }
-
-       xicor_write(X1241REG_SR, 0);
-
-       printk("set_rtc_mmss: %02d:%02d\n", real_minutes, real_seconds);
-
-       return retval;
-}
-
-static unsigned long __init get_swarm_time(void)
-{
-       unsigned int year, mon, day, hour, min, sec, y2k;
-
-       sec = xicor_read(X1241REG_SC);
-       min = xicor_read(X1241REG_MN);
-       hour = xicor_read(X1241REG_HR);
-
-       if (hour & X1241REG_HR_MIL) {
-               hour &= 0x3f;
-       } else {
-               if (hour & 0x20)
-                       hour = (hour & 0xf) + 0x12;
-       }
-
-       sec = BCD2BIN(sec);
-       min = BCD2BIN(min);
-       hour = BCD2BIN(hour);
-
-       day = xicor_read(X1241REG_DT);
-       mon = xicor_read(X1241REG_MO);
-       year = xicor_read(X1241REG_YR);
-       y2k = xicor_read(X1241REG_Y2K);
-
-       day = BCD2BIN(day);
-       mon = BCD2BIN(mon);
-       year = BCD2BIN(year);
-       y2k = BCD2BIN(y2k);
-
-       year += (y2k * 100);
-
-       return mktime(year, mon, day, hour, min, sec);
-}
-
-/*
- *  Bring up the timer at 100 Hz.
- */
-void __init swarm_time_init(void)
-{
-       unsigned int flags;
-       int status;
-
-       /* Set up the scd general purpose timer 0 to cpu 0 */
-       sb1250_time_init();
-
-       /* Establish communication with the Xicor 1241 RTC */
-       /* XXXKW how do I share the SMBus with the I2C subsystem? */
-
-       __raw_writeq(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ));
-       __raw_writeq(0, SMB_CSR(R_SMB_CONTROL));
-
-       if ((status = xicor_read(X1241REG_SR_RTCF)) < 0) {
-               printk("x1241: couldn't detect on SWARM SMBus 1\n");
-       } else {
-               if (status & X1241REG_SR_RTCF)
-                       printk("x1241: battery failed -- time is probably wrong\n");
-               write_seqlock_irqsave(&xtime_lock, flags);
-               xtime.tv_sec = get_swarm_time();
-               xtime.tv_nsec = 0;
-               write_sequnlock_irqrestore(&xtime_lock, flags);
-       }
-}
index 6850a29defcd20b9979c76957bb5a24c0145d82a..acc9ba76c1a9f2611596931b5b1c1b13ccd27fe4 100644 (file)
@@ -87,8 +87,8 @@ static struct platform_device snirm_82596_pdev = {
 
 static struct resource snirm_53c710_rsrc[] = {
        {
-               .start = 0xb9000000,
-               .end   = 0xb90fffff,
+               .start = 0x19000000,
+               .end   = 0x190fffff,
                .flags = IORESOURCE_MEM
        },
        {
@@ -106,8 +106,8 @@ static struct platform_device snirm_53c710_pdev = {
 
 static struct resource sc26xx_rsrc[] = {
        {
-               .start = 0xbc070000,
-               .end   = 0xbc0700ff,
+               .start = 0x1c070000,
+               .end   = 0x1c0700ff,
                .flags = IORESOURCE_MEM
        },
        {
index 4bfda020fdc71015dc37c3d76128f633bed5a894..28a11d8605cece9d2425b9a3a8aaed954c9d07ac 100644 (file)
@@ -88,8 +88,8 @@ static struct platform_device snirm_82596_rm200_pdev = {
 
 static struct resource snirm_53c710_rm200_rsrc[] = {
        {
-               .start = 0xb9000000,
-               .end   = 0xb90fffff,
+               .start = 0x19000000,
+               .end   = 0x190fffff,
                .flags = IORESOURCE_MEM
        },
        {
index a0c11efeaeeb9dd24658c114b5c46fa66bf26e70..40c7c3eeafaf2e740fe0e633aa8e82e8135f6123 100644 (file)
@@ -138,7 +138,6 @@ extern void toshiba_rbtx4927_irq_setup(void);
 char *prom_getcmdline(void);
 
 #ifdef CONFIG_PCI
-#define CONFIG_TX4927BUG_WORKAROUND
 #undef TX4927_SUPPORT_COMMAND_IO
 #undef  TX4927_SUPPORT_PCI_66
 int tx4927_cpu_clock = 100000000;      /* 100MHz */
@@ -669,15 +668,7 @@ void tx4927_pci_setup(void)
 
        /* PCI->GB mappings (MEM 16MB) -not used */
        tx4927_pcicptr->p2gm1plbase = 0xffffffff;
-#ifdef CONFIG_TX4927BUG_WORKAROUND
-       /*
-        * TX4927-PCIC-BUG: P2GM1PUBASE must be 0
-        * if P2GM0PUBASE was 0.
-        */
-       tx4927_pcicptr->p2gm1pubase = 0;
-#else
        tx4927_pcicptr->p2gm1pubase = 0xffffffff;
-#endif
        tx4927_pcicptr->p2gmgbase[1] = 0;
 
        /* PCI->GB mappings (MEM 1MB) -not used */
@@ -910,16 +901,6 @@ void __init toshiba_rbtx4927_setup(void)
        if (tx4927_ccfg_toeon)
                tx4927_ccfgptr->ccfg |= TX4927_CCFG_TOE;
 
-       /* SDRAMC fixup */
-#ifdef CONFIG_TX4927BUG_WORKAROUND
-       /*
-        * TX4927-BUG: INF 01-01-18/ BUG 01-01-22
-        * G-bus timeout error detection is incorrect
-        */
-       if (tx4927_ccfg_toeon)
-               tx4927_sdramcptr->tr |= 0x02000000;     /* RCD:3tck */
-#endif
-
        tx4927_pci_setup();
        if (tx4927_using_backplane == 1)
                printk("backplane board IS installed\n");
index f842783acd863bc4cdc300bddad3921eb3fd16ab..d0d84ec8d63de98428e612484b651a3c2211e554 100644 (file)
@@ -2,4 +2,4 @@
 # Makefile for common code of the NEC VR4100 series.
 #
 
-obj-y  += bcu.o cmu.o icu.o init.o irq.o pmu.o type.o
+obj-y  += bcu.o cmu.o giu.o icu.o init.o irq.o pmu.o rtc.o siu.o type.o
diff --git a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c
new file mode 100644 (file)
index 0000000..d21f6f2
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  NEC VR4100 series GIU platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/cpu.h>
+#include <asm/vr41xx/giu.h>
+#include <asm/vr41xx/irq.h>
+
+static struct resource giu_50pins_pullupdown_resource[] __initdata = {
+       {
+               .start  = 0x0b000100,
+               .end    = 0x0b00011f,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = 0x0b0002e0,
+               .end    = 0x0b0002e3,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = GIUINT_IRQ,
+               .end    = GIUINT_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource giu_36pins_resource[] __initdata = {
+       {
+               .start  = 0x0f000140,
+               .end    = 0x0f00015f,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = GIUINT_IRQ,
+               .end    = GIUINT_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource giu_48pins_resource[] __initdata = {
+       {
+               .start  = 0x0f000140,
+               .end    = 0x0f000167,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = GIUINT_IRQ,
+               .end    = GIUINT_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static int __init vr41xx_giu_add(void)
+{
+       struct platform_device *pdev;
+       struct resource *res;
+       unsigned int num;
+       int retval;
+
+       pdev = platform_device_alloc("GIU", -1);
+       if (!pdev)
+               return -ENOMEM;
+
+       switch (current_cpu_data.cputype) {
+       case CPU_VR4111:
+       case CPU_VR4121:
+               pdev->id = GPIO_50PINS_PULLUPDOWN;
+               res = giu_50pins_pullupdown_resource;
+               num = ARRAY_SIZE(giu_50pins_pullupdown_resource);
+               break;
+       case CPU_VR4122:
+       case CPU_VR4131:
+               pdev->id = GPIO_36PINS;
+               res = giu_36pins_resource;
+               num = ARRAY_SIZE(giu_36pins_resource);
+               break;
+       case CPU_VR4133:
+               pdev->id = GPIO_48PINS_EDGE_SELECT;
+               res = giu_48pins_resource;
+               num = ARRAY_SIZE(giu_48pins_resource);
+               break;
+       default:
+               retval = -ENODEV;
+               goto err_free_device;
+       }
+
+       retval = platform_device_add_resources(pdev, res, num);
+       if (retval)
+               goto err_free_device;
+
+       retval = platform_device_add(pdev);
+       if (retval)
+               goto err_free_device;
+
+       return 0;
+
+err_free_device:
+       platform_device_put(pdev);
+
+       return retval;
+}
+device_initcall(vr41xx_giu_add);
diff --git a/arch/mips/vr41xx/common/rtc.c b/arch/mips/vr41xx/common/rtc.c
new file mode 100644 (file)
index 0000000..cce605b
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *  NEC VR4100 series RTC platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/cpu.h>
+#include <asm/vr41xx/irq.h>
+
+static struct resource rtc_type1_resource[] __initdata = {
+       {
+               .start  = 0x0b0000c0,
+               .end    = 0x0b0000df,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = 0x0b0001c0,
+               .end    = 0x0b0001df,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = ELAPSEDTIME_IRQ,
+               .end    = ELAPSEDTIME_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = RTCLONG1_IRQ,
+               .end    = RTCLONG1_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource rtc_type2_resource[] __initdata = {
+       {
+               .start  = 0x0f000100,
+               .end    = 0x0f00011f,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = 0x0f000120,
+               .end    = 0x0f00013f,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = ELAPSEDTIME_IRQ,
+               .end    = ELAPSEDTIME_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = RTCLONG1_IRQ,
+               .end    = RTCLONG1_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static int __init vr41xx_rtc_add(void)
+{
+       struct platform_device *pdev;
+       struct resource *res;
+       unsigned int num;
+       int retval;
+
+       pdev = platform_device_alloc("RTC", -1);
+       if (!pdev)
+               return -ENOMEM;
+
+       switch (current_cpu_data.cputype) {
+       case CPU_VR4111:
+       case CPU_VR4121:
+               res = rtc_type1_resource;
+               num = ARRAY_SIZE(rtc_type1_resource);
+               break;
+       case CPU_VR4122:
+       case CPU_VR4131:
+       case CPU_VR4133:
+               res = rtc_type2_resource;
+               num = ARRAY_SIZE(rtc_type2_resource);
+               break;
+       default:
+               retval = -ENODEV;
+               goto err_free_device;
+       }
+
+       retval = platform_device_add_resources(pdev, res, num);
+       if (retval)
+               goto err_free_device;
+
+       retval = platform_device_add(pdev);
+       if (retval)
+               goto err_free_device;
+
+       return 0;
+
+err_free_device:
+       platform_device_put(pdev);
+
+       return retval;
+}
+device_initcall(vr41xx_rtc_add);
diff --git a/arch/mips/vr41xx/common/siu.c b/arch/mips/vr41xx/common/siu.c
new file mode 100644 (file)
index 0000000..a1e7741
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  NEC VR4100 series SIU platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/vr41xx/siu.h>
+
+static unsigned int siu_type1_ports[SIU_PORTS_MAX] __initdata = {
+       PORT_VR41XX_SIU,
+       PORT_UNKNOWN,
+};
+
+static struct resource siu_type1_resource[] __initdata = {
+       {
+               .start  = 0x0c000000,
+               .end    = 0x0c00000a,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = SIU_IRQ,
+               .end    = SIU_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static unsigned int siu_type2_ports[SIU_PORTS_MAX] __initdata = {
+       PORT_VR41XX_SIU,
+       PORT_VR41XX_DSIU,
+};
+
+static struct resource siu_type2_resource[] __initdata = {
+       {
+               .start  = 0x0f000800,
+               .end    = 0x0f00080a,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = 0x0f000820,
+               .end    = 0x0f000829,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = SIU_IRQ,
+               .end    = SIU_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = DSIU_IRQ,
+               .end    = DSIU_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static int __init vr41xx_siu_add(void)
+{
+       struct platform_device *pdev;
+       struct resource *res;
+       unsigned int num;
+       int retval;
+
+       pdev = platform_device_alloc("SIU", -1);
+       if (!pdev)
+               return -ENOMEM;
+
+       switch (current_cpu_data.cputype) {
+       case CPU_VR4111:
+       case CPU_VR4121:
+               pdev->dev.platform_data = siu_type1_ports;
+               res = siu_type1_resource;
+               num = ARRAY_SIZE(siu_type1_resource);
+               break;
+       case CPU_VR4122:
+       case CPU_VR4131:
+       case CPU_VR4133:
+               pdev->dev.platform_data = siu_type2_ports;
+               res = siu_type2_resource;
+               num = ARRAY_SIZE(siu_type2_resource);
+               break;
+       default:
+               retval = -ENODEV;
+               goto err_free_device;
+       }
+
+       retval = platform_device_add_resources(pdev, res, num);
+       if (retval)
+               goto err_free_device;
+
+       retval = platform_device_add(pdev);
+       if (retval)
+               goto err_free_device;
+
+       return 0;
+
+err_free_device:
+       platform_device_put(pdev);
+
+       return retval;
+}
+device_initcall(vr41xx_siu_add);
index 5eaeafd30bdfe2710b7e35f325fee9692b751d44..6beee32144c02e45456c5e8c037e8630b1b6f7bb 100644 (file)
@@ -698,8 +698,10 @@ config PCI
          infrastructure code to support PCI bus devices.
 
 config PCI_DOMAINS
-       bool
-       default PCI
+       def_bool PCI
+
+config PCI_SYSCALL
+       def_bool PCI
 
 config PCI_QSPAN
        bool "QSpan PCI"
index e66064b5093a2496ad2e03e9ebd1212ba98ad72b..86982112b0ddb7e39c301aa1ee30202b12b88bbf 100644 (file)
@@ -1047,10 +1047,10 @@ void pcibios_make_OF_bus_map(void)
 #endif /* CONFIG_PPC_OF */
 
 /* Add sysfs properties */
-void pcibios_add_platform_entries(struct pci_dev *pdev)
+int pcibios_add_platform_entries(struct pci_dev *pdev)
 {
 #ifdef CONFIG_PPC_OF
-       device_create_file(&pdev->dev, &dev_attr_devspec);
+       return device_create_file(&pdev->dev, &dev_attr_devspec);
 #endif /* CONFIG_PPC_OF */
 }
 
index 249cca27a9b84ade58c94020534a8aa8a018ee83..e3009a43ac56ed117b553fab9f071593142205bb 100644 (file)
@@ -367,8 +367,10 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
        sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
                dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
        dev->class = get_int_prop(node, "class-code", 0);
+       dev->revision = get_int_prop(node, "revision-id", 0);
 
        DBG("    class: 0x%x\n", dev->class);
+       DBG("    revision: 0x%x\n", dev->revision);
 
        dev->current_state = 4;         /* unknown power state */
        dev->error_state = pci_channel_io_normal;
@@ -876,9 +878,9 @@ static ssize_t pci_show_devspec(struct device *dev,
 }
 static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
 
-void pcibios_add_platform_entries(struct pci_dev *pdev)
+int pcibios_add_platform_entries(struct pci_dev *pdev)
 {
-       device_create_file(&pdev->dev, &dev_attr_devspec);
+       return device_create_file(&pdev->dev, &dev_attr_devspec);
 }
 
 #define ISA_SPACE_MASK 0x1
index ccce2a4a1522f574b49dacf261108a4b43068f09..6bdeeb70b157856a00b6ce22c397a74abeb0d803 100644 (file)
@@ -1237,8 +1237,10 @@ config PCI
          infrastructure code to support PCI bus devices.
 
 config PCI_DOMAINS
-       bool
-       default PCI
+       def_bool PCI
+
+config PCI_SYSCALL
+       def_bool PCI
 
 config MPC83xx_PCI2
        bool "Support for 2nd PCI host controller"
index 5e723c4c2571b0a3dc886032a92681a9927b9d7c..c2ec13bea006aa5e9c63c0683808a2e68d0f8c44 100644 (file)
@@ -633,12 +633,6 @@ void pcibios_make_OF_bus_map(void)
 {
 }
 
-/* Add sysfs properties */
-void pcibios_add_platform_entries(struct pci_dev *pdev)
-{
-}
-
-
 static int __init
 pcibios_init(void)
 {
index 8485a68cd4753ade53df7dcce6771b44d02d9387..032f4b7f42257c7566fee56e084bd88ed6f5bc23 100644 (file)
@@ -2415,7 +2415,6 @@ static struct bin_attribute mv64xxx_hs_reg_attr = { /* Hotswap register */
        .attr = {
                .name = "hs_reg",
                .mode = S_IRUGO | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size  = VAL_LEN_MAX,
        .read  = mv64xxx_hs_reg_read,
index 82b131ddd7ffa17b06bdfb149d53db4bc8951421..9a13b24ee1ab2e751715ce014823d22a60828b54 100644 (file)
@@ -312,7 +312,6 @@ static struct bin_attribute ipl_parameter_attr = {
        .attr = {
                .name = "binary_parameter",
                .mode = S_IRUGO,
-               .owner = THIS_MODULE,
        },
        .size = PAGE_SIZE,
        .read = &ipl_parameter_read,
@@ -336,7 +335,6 @@ static struct bin_attribute ipl_scp_data_attr = {
        .attr = {
                .name = "scp_data",
                .mode = S_IRUGO,
-               .owner = THIS_MODULE,
        },
        .size = PAGE_SIZE,
        .read = &ipl_scp_data_read,
index fbcc00c6c06ea6dff4c0706ac86a5806b1b63b4e..8567cc901942be09a40178388919afea7fdc1d4c 100644 (file)
@@ -210,6 +210,9 @@ config PCI
          CP-1200, JavaEngine-1, Corona, Red October, and Serengeti SGSC.
          All of these platforms are extremely obscure, so say N if unsure.
 
+config PCI_SYSCALL
+       def_bool PCI
+
 source "drivers/pci/Kconfig"
 
 endif
index 89a1b469b93df149b21c1c65c5d1723d36e97e09..6566d13db04fec3c5417cde60c0295319f405c9f 100644 (file)
@@ -320,8 +320,10 @@ config PCI
          doesn't.
 
 config PCI_DOMAINS
-       bool
-       default PCI
+       def_bool PCI
+
+config PCI_SYSCALL
+       def_bool PCI
 
 source "drivers/pci/Kconfig"
 
index 81f4a5ea05f7ab948e307daa1853f53d1b554fbd..55ad1b899bb8e945a3e049d09ef13e5e1fd167a5 100644 (file)
@@ -448,6 +448,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
                 */
                pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
                dev->class = class >> 8;
+               dev->revision = class & 0xff;
 
                sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
                        dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
index 5ce94430c019cfe90bb647082d0c63e41e0c09e5..8bdd25ac15425d40f3bb7340f87a5dd70ddc140d 100644 (file)
@@ -427,6 +427,10 @@ config NR_CPUS
          This is purely to save memory - each supported CPU requires
          memory in the static kernel configuration.
 
+config PHYSICAL_ALIGN
+       hex
+       default "0x200000"
+
 config HOTPLUG_CPU
        bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)"
        depends on SMP && HOTPLUG && EXPERIMENTAL
index ee6f6505f95f98d14d087066a64d154de8893f01..67096389de1f1f7d1323f9ef6bead27e284c742c 100644 (file)
@@ -1,135 +1,9 @@
 #
 # arch/x86_64/boot/Makefile
 #
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1994 by Linus Torvalds
-#
-
-# ROOT_DEV specifies the default root-device when making the image.
-# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
-# the default of FLOPPY is used by 'build'.
-
-ROOT_DEV := CURRENT
-
-# If you want to preset the SVGA mode, uncomment the next line and
-# set SVGA_MODE to whatever number you want.
-# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
-# The number is the same as you would ordinarily press at bootup.
-
-SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
-
-# If you want the RAM disk device, define this to be the size in blocks.
-
-#RAMDISK := -DRAMDISK=512
-
-targets                := vmlinux.bin bootsect bootsect.o \
-                  setup setup.o bzImage mtools.conf
-
-EXTRA_CFLAGS := -m32
-
-hostprogs-y    := tools/build
-HOST_EXTRACFLAGS += $(LINUXINCLUDE)
-subdir-                := compressed/  #Let make clean descend in compressed/
-# ---------------------------------------------------------------------------
-
-$(obj)/bzImage: IMAGE_OFFSET := 0x100000
-$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
-$(obj)/bzImage: BUILDFLAGS   := -b
-
-quiet_cmd_image = BUILD   $@
-cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
-           $(obj)/vmlinux.bin $(ROOT_DEV) > $@
-
-$(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
-                             $(obj)/vmlinux.bin $(obj)/tools/build FORCE
-       $(call if_changed,image)
-       @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
-
-$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
-       $(call if_changed,objcopy)
-
-LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
-LDFLAGS_setup   := -Ttext 0x0 -s --oformat binary -e begtext
-
-$(obj)/setup $(obj)/bootsect: %: %.o FORCE
-       $(call if_changed,ld)
-
-$(obj)/compressed/vmlinux: FORCE
-       $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
-
-# Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel
-FDARGS = 
-# Set this if you want an initrd included with the zdisk/fdimage/isoimage kernel
-FDINITRD =
-
-image_cmdline = default linux $(FDARGS) $(if $(FDINITRD),initrd=initrd.img,)
-
-$(obj)/mtools.conf: $(src)/mtools.conf.in
-       sed -e 's|@OBJ@|$(obj)|g' < $< > $@
-
-# This requires write access to /dev/fd0
-zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
-       MTOOLSRC=$(obj)/mtools.conf mformat a:                  ; sync
-       syslinux /dev/fd0                                       ; sync
-       echo '$(image_cmdline)' | \
-               MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg
-       if [ -f '$(FDINITRD)' ] ; then \
-               MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' a:initrd.img ; \
-       fi
-       MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux  ; sync
-
-# These require being root or having syslinux 2.02 or higher installed
-fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
-       dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
-       MTOOLSRC=$(obj)/mtools.conf mformat v:                  ; sync
-       syslinux $(obj)/fdimage                                 ; sync
-       echo '$(image_cmdline)' | \
-               MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
-       if [ -f '$(FDINITRD)' ] ; then \
-               MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' v:initrd.img ; \
-       fi
-       MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux  ; sync
-
-fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
-       dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
-       MTOOLSRC=$(obj)/mtools.conf mformat w:                  ; sync
-       syslinux $(obj)/fdimage                                 ; sync
-       echo '$(image_cmdline)' | \
-               MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
-       if [ -f '$(FDINITRD)' ] ; then \
-               MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' w:initrd.img ; \
-       fi
-       MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux  ; sync
-
-isoimage: $(BOOTIMAGE)
-       -rm -rf $(obj)/isoimage
-       mkdir $(obj)/isoimage
-       for i in lib lib64 share end ; do \
-               if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \
-                       cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \
-                       break ; \
-               fi ; \
-               if [ $$i = end ] ; then exit 1 ; fi ; \
-       done
-       cp $(BOOTIMAGE) $(obj)/isoimage/linux
-       echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg
-       if [ -f '$(FDINITRD)' ] ; then \
-               cp '$(FDINITRD)' $(obj)/isoimage/initrd.img ; \
-       fi
-       mkisofs -J -r -o $(obj)/image.iso -b isolinux.bin -c boot.cat \
-               -no-emul-boot -boot-load-size 4 -boot-info-table \
-               $(obj)/isoimage
-       rm -rf $(obj)/isoimage
-
-zlilo: $(BOOTIMAGE)
-       if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
-       if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
-       cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz
-       cp System.map $(INSTALL_PATH)/
-       if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+# The actual boot code is shared with i386 including the Makefile.
+# So tell kbuild that we fetch the code from i386 and include the
+# Makefile from i386 too.
 
-install:
-       sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
+src := arch/i386/boot
+include $(src)/Makefile
diff --git a/arch/x86_64/boot/bootsect.S b/arch/x86_64/boot/bootsect.S
deleted file mode 100644 (file)
index 011b7a4..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *     bootsect.S              Copyright (C) 1991, 1992 Linus Torvalds
- *
- *     modified by Drew Eckhardt
- *     modified by Bruce Evans (bde)
- *     modified by Chris Noe (May 1999) (as86 -> gas)
- *     gutted by H. Peter Anvin (Jan 2003)
- *
- * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
- * addresses must be multiplied by 16 to obtain their respective linear
- * addresses. To avoid confusion, linear addresses are written using leading
- * hex while segment addresses are written as segment:offset.
- *
- */
-
-#include <asm/boot.h>
-
-SETUPSECTS     = 4                     /* default nr of setup-sectors */
-BOOTSEG                = 0x07C0                /* original address of boot-sector */
-INITSEG                = DEF_INITSEG           /* we move boot here - out of the way */
-SETUPSEG       = DEF_SETUPSEG          /* setup starts here */
-SYSSEG         = DEF_SYSSEG            /* system loaded at 0x10000 (65536) */
-SYSSIZE                = DEF_SYSSIZE           /* system size: # of 16-byte clicks */
-                                       /* to be loaded */
-ROOT_DEV       = 0                     /* ROOT_DEV is now written by "build" */
-SWAP_DEV       = 0                     /* SWAP_DEV is now written by "build" */
-
-#ifndef SVGA_MODE
-#define SVGA_MODE ASK_VGA
-#endif
-
-#ifndef RAMDISK
-#define RAMDISK 0
-#endif
-
-#ifndef ROOT_RDONLY
-#define ROOT_RDONLY 1
-#endif
-
-.code16
-.text
-
-.global _start
-_start:
-
-       # Normalize the start address
-       jmpl    $BOOTSEG, $start2
-
-start2:
-       movw    %cs, %ax
-       movw    %ax, %ds
-       movw    %ax, %es
-       movw    %ax, %ss
-       movw    $0x7c00, %sp
-       sti
-       cld
-
-       movw    $bugger_off_msg, %si
-
-msg_loop:
-       lodsb
-       andb    %al, %al
-       jz      die
-       movb    $0xe, %ah
-       movw    $7, %bx
-       int     $0x10
-       jmp     msg_loop
-
-die:
-       # Allow the user to press a key, then reboot
-       xorw    %ax, %ax
-       int     $0x16
-       int     $0x19
-
-       # int 0x19 should never return.  In case it does anyway,
-       # invoke the BIOS reset code...
-       ljmp    $0xf000,$0xfff0
-
-
-bugger_off_msg:
-       .ascii  "Direct booting from floppy is no longer supported.\r\n"
-       .ascii  "Please use a boot loader program instead.\r\n"
-       .ascii  "\n"
-       .ascii  "Remove disk and press any key to reboot . . .\r\n"
-       .byte   0
-
-
-       # Kernel attributes; used by setup
-
-       .org 497
-setup_sects:   .byte SETUPSECTS
-root_flags:    .word ROOT_RDONLY
-syssize:       .word SYSSIZE
-swap_dev:      .word SWAP_DEV
-ram_size:      .word RAMDISK
-vid_mode:      .word SVGA_MODE
-root_dev:      .word ROOT_DEV
-boot_flag:     .word 0xAA55
index 705a3e33d7e176009cc8fb135620f80d88821dd8..c9f2da7496c14d738b0c8453dd835dd70db9cf96 100644 (file)
@@ -7,11 +7,12 @@
 #
 
 targets                := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
-EXTRA_AFLAGS   := -traditional
 
-# cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with
-# -m32
-CFLAGS := -m64 -D__KERNEL__ -Iinclude -O2  -fno-strict-aliasing -fPIC -mcmodel=small -fno-builtin
+CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2  \
+         -fno-strict-aliasing -fPIC -mcmodel=small \
+          $(call cc-option, -ffreestanding) \
+          $(call cc-option, -fno-stack-protector)
+AFLAGS  := $(CFLAGS) -D__ASSEMBLY__
 LDFLAGS := -m elf_x86_64
 
 LDFLAGS_vmlinux := -T
index f9d5692a0106e4c0ee311d034bd5eb0ef7702e3b..1312bfaff306866319fcbb8dec3caf06f933c0d1 100644 (file)
@@ -46,10 +46,10 @@ startup_32:
  * at and where we were actually loaded at.  This can only be done
  * with a short local call on x86.  Nothing  else will tell us what
  * address we are running at.  The reserved chunk of the real-mode
- * data at 0x34-0x3f are used as the stack for this calculation.
- * Only 4 bytes are needed.
+ * data at 0x1e4 (defined as a scratch field) are used as the stack
+ * for this calculation. Only 4 bytes are needed.
  */
-       leal    0x40(%esi), %esp
+       leal    (0x1e4+4)(%esi), %esp
        call    1f
 1:     popl    %ebp
        subl    $1b, %ebp
diff --git a/arch/x86_64/boot/install.sh b/arch/x86_64/boot/install.sh
deleted file mode 100644 (file)
index baaa236..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-. $srctree/arch/i386/boot/install.sh
diff --git a/arch/x86_64/boot/mtools.conf.in b/arch/x86_64/boot/mtools.conf.in
deleted file mode 100644 (file)
index efd6d24..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# mtools configuration file for "make (b)zdisk"
-#
-
-# Actual floppy drive
-drive a:
-  file="/dev/fd0"
-
-# 1.44 MB floppy disk image
-drive v:
-  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter
-
-# 2.88 MB floppy disk image (mostly for virtual uses)
-drive w:
-  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
-
-
diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S
deleted file mode 100644 (file)
index e9e33f9..0000000
+++ /dev/null
@@ -1,826 +0,0 @@
-/*
- *     setup.S         Copyright (C) 1991, 1992 Linus Torvalds
- *
- * setup.s is responsible for getting the system data from the BIOS,
- * and putting them into the appropriate places in system memory.
- * both setup.s and system has been loaded by the bootblock.
- *
- * This code asks the bios for memory/disk/other parameters, and
- * puts them in a "safe" place: 0x90000-0x901FF, ie where the
- * boot-block used to be. It is then up to the protected mode
- * system to read them from there before the area is overwritten
- * for buffer-blocks.
- *
- * Move PS/2 aux init code to psaux.c
- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
- *
- * some changes and additional features by Christoph Niemann,
- * March 1993/June 1994 (Christoph.Niemann@linux.org)
- *
- * add APM BIOS checking by Stephen Rothwell, May 1994
- * (sfr@canb.auug.org.au)
- *
- * High load stuff, initrd support and position independency
- * by Hans Lermen & Werner Almesberger, February 1996
- * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
- *
- * Video handling moved to video.S by Martin Mares, March 1996
- * <mj@k332.feld.cvut.cz>
- *
- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
- * parsons) to avoid loadlin confusion, July 1997
- *
- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
- * <stiker@northlink.com>
- *
- * Fix to work around buggy BIOSes which don't use carry bit correctly
- * and/or report extended memory in CX/DX for e801h memory size detection 
- * call.  As a result the kernel got wrong figures.  The int15/e801h docs
- * from Ralf Brown interrupt list seem to indicate AX/BX should be used
- * anyway.  So to avoid breaking many machines (presumably there was a reason
- * to orginally use CX/DX instead of AX/BX), we do a kludge to see
- * if CX/DX have been changed in the e801 call and if so use AX/BX .
- * Michael Miller, April 2001 <michaelm@mjmm.org>
- *
- * Added long mode checking and SSE force. March 2003, Andi Kleen.             
- */
-
-#include <asm/segment.h>
-#include <linux/utsrelease.h>
-#include <linux/compile.h>
-#include <asm/boot.h>
-#include <asm/e820.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-
-/* Signature words to ensure LILO loaded us right */
-#define SIG1   0xAA55
-#define SIG2   0x5A5A
-
-INITSEG  = DEF_INITSEG         # 0x9000, we move boot here, out of the way
-SYSSEG   = DEF_SYSSEG          # 0x1000, system loaded at 0x10000 (65536).
-SETUPSEG = DEF_SETUPSEG                # 0x9020, this is the current segment
-                               # ... and the former contents of CS
-
-DELTA_INITSEG = SETUPSEG - INITSEG     # 0x0020
-
-.code16
-.globl begtext, begdata, begbss, endtext, enddata, endbss
-
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
-
-start:
-       jmp     trampoline
-
-# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
-
-               .ascii  "HdrS"          # header signature
-               .word   0x0206          # header version number (>= 0x0105)
-                                       # or else old loadlin-1.5 will fail)
-realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
-start_sys_seg: .word   SYSSEG
-               .word   kernel_version  # pointing to kernel version string
-                                       # above section of header is compatible
-                                       # with loadlin-1.5 (header v1.5). Don't
-                                       # change it.
-
-type_of_loader:        .byte   0               # = 0, old one (LILO, Loadlin,
-                                       #      Bootlin, SYSLX, bootsect...)
-                                       # See Documentation/i386/boot.txt for
-                                       # assigned ids
-       
-# flags, unused bits must be zero (RFU) bit within loadflags
-loadflags:
-LOADED_HIGH    = 1                     # If set, the kernel is loaded high
-CAN_USE_HEAP   = 0x80                  # If set, the loader also has set
-                                       # heap_end_ptr to tell how much
-                                       # space behind setup.S can be used for
-                                       # heap purposes.
-                                       # Only the loader knows what is free
-#ifndef __BIG_KERNEL__
-               .byte   0
-#else
-               .byte   LOADED_HIGH
-#endif
-
-setup_move_size: .word  0x8000         # size to move, when setup is not
-                                       # loaded at 0x90000. We will move setup 
-                                       # to 0x90000 then just before jumping
-                                       # into the kernel. However, only the
-                                       # loader knows how much data behind
-                                       # us also needs to be loaded.
-
-code32_start:                          # here loaders can put a different
-                                       # start address for 32-bit code.
-#ifndef __BIG_KERNEL__
-               .long   0x1000          #   0x1000 = default for zImage
-#else
-               .long   0x100000        # 0x100000 = default for big kernel
-#endif
-
-ramdisk_image: .long   0               # address of loaded ramdisk image
-                                       # Here the loader puts the 32-bit
-                                       # address where it loaded the image.
-                                       # This only will be read by the kernel.
-
-ramdisk_size:  .long   0               # its size in bytes
-
-bootsect_kludge:
-               .long   0               # obsolete
-
-heap_end_ptr:  .word   modelist+1024   # (Header version 0x0201 or later)
-                                       # space from here (exclusive) down to
-                                       # end of setup code can be used by setup
-                                       # for local heap purposes.
-
-pad1:          .word   0
-cmd_line_ptr:  .long 0                 # (Header version 0x0202 or later)
-                                       # If nonzero, a 32-bit pointer
-                                       # to the kernel command line.
-                                       # The command line should be
-                                       # located between the start of
-                                       # setup and the end of low
-                                       # memory (0xa0000), or it may
-                                       # get overwritten before it
-                                       # gets read.  If this field is
-                                       # used, there is no longer
-                                       # anything magical about the
-                                       # 0x90000 segment; the setup
-                                       # can be located anywhere in
-                                       # low memory 0x10000 or higher.
-
-ramdisk_max:   .long 0xffffffff
-kernel_alignment:  .long 0x200000       # physical addr alignment required for
-                                       # protected mode relocatable kernel
-#ifdef CONFIG_RELOCATABLE
-relocatable_kernel:    .byte 1
-#else
-relocatable_kernel:    .byte 0
-#endif
-pad2:                  .byte 0
-pad3:                  .word 0
-
-cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
-                                                #added with boot protocol
-                                                #version 2.06
-
-trampoline:    call    start_of_setup
-               .align 16
-                                       # The offset at this point is 0x240
-               .space  (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff)
-# End of setup header #####################################################
-
-start_of_setup:
-# Bootlin depends on this being done early
-       movw    $0x01500, %ax
-       movb    $0x81, %dl
-       int     $0x13
-
-#ifdef SAFE_RESET_DISK_CONTROLLER
-# Reset the disk controller.
-       movw    $0x0000, %ax
-       movb    $0x80, %dl
-       int     $0x13
-#endif
-
-# Set %ds = %cs, we know that SETUPSEG = %cs at this point
-       movw    %cs, %ax                # aka SETUPSEG
-       movw    %ax, %ds
-# Check signature at end of setup
-       cmpw    $SIG1, setup_sig1
-       jne     bad_sig
-
-       cmpw    $SIG2, setup_sig2
-       jne     bad_sig
-
-       jmp     good_sig1
-
-# Routine to print asciiz string at ds:si
-prtstr:
-       lodsb
-       andb    %al, %al
-       jz      fin
-
-       call    prtchr
-       jmp     prtstr
-
-fin:   ret
-
-# Space printing
-prtsp2:        call    prtspc          # Print double space
-prtspc:        movb    $0x20, %al      # Print single space (note: fall-thru)
-
-prtchr:        
-       pushw   %ax
-       pushw   %cx
-       movw    $0007,%bx
-       movw    $0x01, %cx
-       movb    $0x0e, %ah
-       int     $0x10
-       popw    %cx
-       popw    %ax
-       ret
-
-beep:  movb    $0x07, %al
-       jmp     prtchr
-       
-no_sig_mess: .string   "No setup signature found ..."
-
-good_sig1:
-       jmp     good_sig
-
-# We now have to find the rest of the setup code/data
-bad_sig:
-       movw    %cs, %ax                        # SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # INITSEG
-       movw    %ax, %ds
-       xorb    %bh, %bh
-       movb    (497), %bl                      # get setup sect from bootsect
-       subw    $4, %bx                         # LILO loads 4 sectors of setup
-       shlw    $8, %bx                         # convert to words (1sect=2^8 words)
-       movw    %bx, %cx
-       shrw    $3, %bx                         # convert to segment
-       addw    $SYSSEG, %bx
-       movw    %bx, %cs:start_sys_seg
-# Move rest of setup code/data to here
-       movw    $2048, %di                      # four sectors loaded by LILO
-       subw    %si, %si
-       movw    %cs, %ax                        # aka SETUPSEG
-       movw    %ax, %es
-       movw    $SYSSEG, %ax
-       movw    %ax, %ds
-       rep
-       movsw
-       movw    %cs, %ax                        # aka SETUPSEG
-       movw    %ax, %ds
-       cmpw    $SIG1, setup_sig1
-       jne     no_sig
-
-       cmpw    $SIG2, setup_sig2
-       jne     no_sig
-
-       jmp     good_sig
-
-no_sig:
-       lea     no_sig_mess, %si
-       call    prtstr
-
-no_sig_loop:
-       jmp     no_sig_loop
-
-good_sig:
-       movw    %cs, %ax                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       movw    %ax, %ds
-# Check if an old loader tries to load a big-kernel
-       testb   $LOADED_HIGH, %cs:loadflags     # Do we have a big kernel?
-       jz      loader_ok                       # No, no danger for old loaders.
-
-       cmpb    $0, %cs:type_of_loader          # Do we have a loader that
-                                               # can deal with us?
-       jnz     loader_ok                       # Yes, continue.
-
-       pushw   %cs                             # No, we have an old loader,
-       popw    %ds                             # die. 
-       lea     loader_panic_mess, %si
-       call    prtstr
-
-       jmp     no_sig_loop
-
-loader_panic_mess: .string "Wrong loader, giving up..."
-
-loader_ok:
-       /* check for long mode. */
-       /* we have to do this before the VESA setup, otherwise the user
-          can't see the error message. */
-       
-       pushw   %ds
-       movw    %cs,%ax
-       movw    %ax,%ds
-       
-       call verify_cpu
-       testl %eax,%eax
-       jz sse_ok
-
-no_longmode:
-       call    beep
-       lea     long_mode_panic,%si
-       call    prtstr
-no_longmode_loop:              
-       jmp     no_longmode_loop
-long_mode_panic:
-       .string "Your CPU does not support long mode. Use a 32bit distribution."
-       .byte 0
-
-#include "../kernel/verify_cpu.S"
-sse_ok:
-       popw    %ds
-       
-# tell BIOS we want to go to long mode
-       movl  $0xec00,%eax      # declare target operating mode
-       movl  $2,%ebx           # long mode
-       int $0x15                       
-       
-# Get memory size (extended mem, kB)
-
-       xorl    %eax, %eax
-       movl    %eax, (0x1e0)
-#ifndef STANDARD_MEMORY_BIOS_CALL
-       movb    %al, (E820NR)
-# Try three different memory detection schemes.  First, try
-# e820h, which lets us assemble a memory map, then try e801h,
-# which returns a 32-bit memory size, and finally 88h, which
-# returns 0-64m
-
-# method E820H:
-# the memory map from hell.  e820h returns memory classified into
-# a whole bunch of different types, and allows memory holes and
-# everything.  We scan through this memory map and build a list
-# of the first 32 memory areas, which we return at [E820MAP].
-# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.
-
-#define SMAP  0x534d4150
-
-meme820:
-       xorl    %ebx, %ebx                      # continuation counter
-       movw    $E820MAP, %di                   # point into the whitelist
-                                               # so we can have the bios
-                                               # directly write into it.
-
-jmpe820:
-       movl    $0x0000e820, %eax               # e820, upper word zeroed
-       movl    $SMAP, %edx                     # ascii 'SMAP'
-       movl    $20, %ecx                       # size of the e820rec
-       pushw   %ds                             # data record.
-       popw    %es
-       int     $0x15                           # make the call
-       jc      bail820                         # fall to e801 if it fails
-
-       cmpl    $SMAP, %eax                     # check the return is `SMAP'
-       jne     bail820                         # fall to e801 if it fails
-
-#      cmpl    $1, 16(%di)                     # is this usable memory?
-#      jne     again820
-
-       # If this is usable memory, we save it by simply advancing %di by
-       # sizeof(e820rec).
-       #
-good820:
-       movb    (E820NR), %al                   # up to 128 entries
-       cmpb    $E820MAX, %al
-       jae     bail820
-
-       incb    (E820NR)
-       movw    %di, %ax
-       addw    $20, %ax
-       movw    %ax, %di
-again820:
-       cmpl    $0, %ebx                        # check to see if
-       jne     jmpe820                         # %ebx is set to EOF
-bail820:
-
-
-# method E801H:
-# memory size is in 1k chunksizes, to avoid confusing loadlin.
-# we store the 0xe801 memory size in a completely different place,
-# because it will most likely be longer than 16 bits.
-# (use 1e0 because that's what Larry Augustine uses in his
-# alternative new memory detection scheme, and it's sensible
-# to write everything into the same place.)
-
-meme801:
-       stc                                     # fix to work around buggy
-       xorw    %cx,%cx                         # BIOSes which don't clear/set
-       xorw    %dx,%dx                         # carry on pass/error of
-                                               # e801h memory size call
-                                               # or merely pass cx,dx though
-                                               # without changing them.
-       movw    $0xe801, %ax
-       int     $0x15
-       jc      mem88
-
-       cmpw    $0x0, %cx                       # Kludge to handle BIOSes
-       jne     e801usecxdx                     # which report their extended
-       cmpw    $0x0, %dx                       # memory in AX/BX rather than
-       jne     e801usecxdx                     # CX/DX.  The spec I have read
-       movw    %ax, %cx                        # seems to indicate AX/BX 
-       movw    %bx, %dx                        # are more reasonable anyway...
-
-e801usecxdx:
-       andl    $0xffff, %edx                   # clear sign extend
-       shll    $6, %edx                        # and go from 64k to 1k chunks
-       movl    %edx, (0x1e0)                   # store extended memory size
-       andl    $0xffff, %ecx                   # clear sign extend
-       addl    %ecx, (0x1e0)                   # and add lower memory into
-                                               # total size.
-
-# Ye Olde Traditional Methode.  Returns the memory size (up to 16mb or
-# 64mb, depending on the bios) in ax.
-mem88:
-
-#endif
-       movb    $0x88, %ah
-       int     $0x15
-       movw    %ax, (2)
-
-# Set the keyboard repeat rate to the max
-       movw    $0x0305, %ax
-       xorw    %bx, %bx
-       int     $0x16
-
-# Check for video adapter and its parameters and allow the
-# user to browse video modes.
-       call    video                           # NOTE: we need %ds pointing
-                                               # to bootsector
-
-# Get hd0 data...
-       xorw    %ax, %ax
-       movw    %ax, %ds
-       ldsw    (4 * 0x41), %si
-       movw    %cs, %ax                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       pushw   %ax
-       movw    %ax, %es
-       movw    $0x0080, %di
-       movw    $0x10, %cx
-       pushw   %cx
-       cld
-       rep
-       movsb
-# Get hd1 data...
-       xorw    %ax, %ax
-       movw    %ax, %ds
-       ldsw    (4 * 0x46), %si
-       popw    %cx
-       popw    %es
-       movw    $0x0090, %di
-       rep
-       movsb
-# Check that there IS a hd1 :-)
-       movw    $0x01500, %ax
-       movb    $0x81, %dl
-       int     $0x13
-       jc      no_disk1
-       
-       cmpb    $3, %ah
-       je      is_disk1
-
-no_disk1:
-       movw    %cs, %ax                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       movw    %ax, %es
-       movw    $0x0090, %di
-       movw    $0x10, %cx
-       xorw    %ax, %ax
-       cld
-       rep
-       stosb
-is_disk1:
-
-# Check for PS/2 pointing device
-       movw    %cs, %ax                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       movw    %ax, %ds
-       movb    $0, (0x1ff)                     # default is no pointing device
-       int     $0x11                           # int 0x11: equipment list
-       testb   $0x04, %al                      # check if mouse installed
-       jz      no_psmouse
-
-       movb    $0xAA, (0x1ff)                  # device present
-no_psmouse:
-
-#include "../../i386/boot/edd.S"
-
-# Now we want to move to protected mode ...
-       cmpw    $0, %cs:realmode_swtch
-       jz      rmodeswtch_normal
-
-       lcall   *%cs:realmode_swtch
-
-       jmp     rmodeswtch_end
-
-rmodeswtch_normal:
-        pushw  %cs
-       call    default_switch
-
-rmodeswtch_end:
-# we get the code32 start address and modify the below 'jmpi'
-# (loader may have changed it)
-       movl    %cs:code32_start, %eax
-       movl    %eax, %cs:code32
-
-# Now we move the system to its rightful place ... but we check if we have a
-# big-kernel. In that case we *must* not move it ...
-       testb   $LOADED_HIGH, %cs:loadflags
-       jz      do_move0                        # .. then we have a normal low
-                                               # loaded zImage
-                                               # .. or else we have a high
-                                               # loaded bzImage
-       jmp     end_move                        # ... and we skip moving
-
-do_move0:
-       movw    $0x100, %ax                     # start of destination segment
-       movw    %cs, %bp                        # aka SETUPSEG
-       subw    $DELTA_INITSEG, %bp             # aka INITSEG
-       movw    %cs:start_sys_seg, %bx          # start of source segment
-       cld
-do_move:
-       movw    %ax, %es                        # destination segment
-       incb    %ah                             # instead of add ax,#0x100
-       movw    %bx, %ds                        # source segment
-       addw    $0x100, %bx
-       subw    %di, %di
-       subw    %si, %si
-       movw    $0x800, %cx
-       rep
-       movsw
-       cmpw    %bp, %bx                        # assume start_sys_seg > 0x200,
-                                               # so we will perhaps read one
-                                               # page more than needed, but
-                                               # never overwrite INITSEG
-                                               # because destination is a
-                                               # minimum one page below source
-       jb      do_move
-
-end_move:
-# then we load the segment descriptors
-       movw    %cs, %ax                        # aka SETUPSEG
-       movw    %ax, %ds
-               
-# Check whether we need to be downward compatible with version <=201
-       cmpl    $0, cmd_line_ptr
-       jne     end_move_self           # loader uses version >=202 features
-       cmpb    $0x20, type_of_loader
-       je      end_move_self           # bootsect loader, we know of it
-
-# Boot loader doesnt support boot protocol version 2.02.
-# If we have our code not at 0x90000, we need to move it there now.
-# We also then need to move the params behind it (commandline)
-# Because we would overwrite the code on the current IP, we move
-# it in two steps, jumping high after the first one.
-       movw    %cs, %ax
-       cmpw    $SETUPSEG, %ax
-       je      end_move_self
-
-       cli                                     # make sure we really have
-                                               # interrupts disabled !
-                                               # because after this the stack
-                                               # should not be used
-       subw    $DELTA_INITSEG, %ax             # aka INITSEG
-       movw    %ss, %dx
-       cmpw    %ax, %dx
-       jb      move_self_1
-
-       addw    $INITSEG, %dx
-       subw    %ax, %dx                        # this will go into %ss after
-                                               # the move
-move_self_1:
-       movw    %ax, %ds
-       movw    $INITSEG, %ax                   # real INITSEG
-       movw    %ax, %es
-       movw    %cs:setup_move_size, %cx
-       std                                     # we have to move up, so we use
-                                               # direction down because the
-                                               # areas may overlap
-       movw    %cx, %di
-       decw    %di
-       movw    %di, %si
-       subw    $move_self_here+0x200, %cx
-       rep
-       movsb
-       ljmp    $SETUPSEG, $move_self_here
-
-move_self_here:
-       movw    $move_self_here+0x200, %cx
-       rep
-       movsb
-       movw    $SETUPSEG, %ax
-       movw    %ax, %ds
-       movw    %dx, %ss
-end_move_self:                                 # now we are at the right place
-       lidt    idt_48                          # load idt with 0,0
-       xorl    %eax, %eax                      # Compute gdt_base
-       movw    %ds, %ax                        # (Convert %ds:gdt to a linear ptr)
-       shll    $4, %eax
-       addl    $gdt, %eax
-       movl    %eax, (gdt_48+2)
-       lgdt    gdt_48                          # load gdt with whatever is
-                                               # appropriate
-
-# that was painless, now we enable a20
-       call    empty_8042
-
-       movb    $0xD1, %al                      # command write
-       outb    %al, $0x64
-       call    empty_8042
-
-       movb    $0xDF, %al                      # A20 on
-       outb    %al, $0x60
-       call    empty_8042
-
-#
-#      You must preserve the other bits here. Otherwise embarrasing things
-#      like laptops powering off on boot happen. Corrected version by Kira
-#      Brown from Linux 2.2
-#
-       inb     $0x92, %al                      # 
-       orb     $02, %al                        # "fast A20" version
-       outb    %al, $0x92                      # some chips have only this
-
-# wait until a20 really *is* enabled; it can take a fair amount of
-# time on certain systems; Toshiba Tecras are known to have this
-# problem.  The memory location used here (0x200) is the int 0x80
-# vector, which should be safe to use.
-
-       xorw    %ax, %ax                        # segment 0x0000
-       movw    %ax, %fs
-       decw    %ax                             # segment 0xffff (HMA)
-       movw    %ax, %gs
-a20_wait:
-       incw    %ax                             # unused memory location <0xfff0
-       movw    %ax, %fs:(0x200)                # we use the "int 0x80" vector
-       cmpw    %gs:(0x210), %ax                # and its corresponding HMA addr
-       je      a20_wait                        # loop until no longer aliased
-
-# make sure any possible coprocessor is properly reset..
-       xorw    %ax, %ax
-       outb    %al, $0xf0
-       call    delay
-
-       outb    %al, $0xf1
-       call    delay
-
-# well, that went ok, I hope. Now we mask all interrupts - the rest
-# is done in init_IRQ().
-       movb    $0xFF, %al                      # mask all interrupts for now
-       outb    %al, $0xA1
-       call    delay
-       
-       movb    $0xFB, %al                      # mask all irq's but irq2 which
-       outb    %al, $0x21                      # is cascaded
-
-# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
-# need no steenking BIOS anyway (except for the initial loading :-).
-# The BIOS-routine wants lots of unnecessary data, and it's less
-# "interesting" anyway. This is how REAL programmers do it.
-#
-# Well, now's the time to actually move into protected mode. To make
-# things as simple as possible, we do no register set-up or anything,
-# we let the gnu-compiled 32-bit programs do that. We just jump to
-# absolute address 0x1000 (or the loader supplied one),
-# in 32-bit protected mode.
-#
-# Note that the short jump isn't strictly needed, although there are
-# reasons why it might be a good idea. It won't hurt in any case.
-       movw    $1, %ax                         # protected mode (PE) bit
-       lmsw    %ax                             # This is it!
-       jmp     flush_instr
-
-flush_instr:
-       xorw    %bx, %bx                        # Flag to indicate a boot
-       xorl    %esi, %esi                      # Pointer to real-mode code
-       movw    %cs, %si
-       subw    $DELTA_INITSEG, %si
-       shll    $4, %esi                        # Convert to 32-bit pointer
-# NOTE: For high loaded big kernels we need a
-#      jmpi    0x100000,__KERNEL_CS
-#
-#      but we yet haven't reloaded the CS register, so the default size 
-#      of the target offset still is 16 bit.
-#      However, using an operand prefix (0x66), the CPU will properly
-#      take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
-#      Manual, Mixing 16-bit and 32-bit code, page 16-6)
-
-       .byte 0x66, 0xea                        # prefix + jmpi-opcode
-code32:        .long   0x1000                          # will be set to 0x100000
-                                               # for big kernels
-       .word   __KERNEL_CS
-
-# Here's a bunch of information about your current kernel..
-kernel_version:        .ascii  UTS_RELEASE
-               .ascii  " ("
-               .ascii  LINUX_COMPILE_BY
-               .ascii  "@"
-               .ascii  LINUX_COMPILE_HOST
-               .ascii  ") "
-               .ascii  UTS_VERSION
-               .byte   0
-
-# This is the default real mode switch routine.
-# to be called just before protected mode transition
-default_switch:
-       cli                                     # no interrupts allowed !
-       movb    $0x80, %al                      # disable NMI for bootup
-                                               # sequence
-       outb    %al, $0x70
-       lret
-
-
-# This routine checks that the keyboard command queue is empty
-# (after emptying the output buffers)
-#
-# Some machines have delusions that the keyboard buffer is always full
-# with no keyboard attached...
-#
-# If there is no keyboard controller, we will usually get 0xff
-# to all the reads.  With each IO taking a microsecond and
-# a timeout of 100,000 iterations, this can take about half a
-# second ("delay" == outb to port 0x80). That should be ok,
-# and should also be plenty of time for a real keyboard controller
-# to empty.
-#
-
-empty_8042:
-       pushl   %ecx
-       movl    $100000, %ecx
-
-empty_8042_loop:
-       decl    %ecx
-       jz      empty_8042_end_loop
-
-       call    delay
-
-       inb     $0x64, %al                      # 8042 status port
-       testb   $1, %al                         # output buffer?
-       jz      no_output
-
-       call    delay
-       inb     $0x60, %al                      # read it
-       jmp     empty_8042_loop
-
-no_output:
-       testb   $2, %al                         # is input buffer full?
-       jnz     empty_8042_loop                 # yes - loop
-empty_8042_end_loop:
-       popl    %ecx
-       ret
-
-# Read the cmos clock. Return the seconds in al
-gettime:
-       pushw   %cx
-       movb    $0x02, %ah
-       int     $0x1a
-       movb    %dh, %al                        # %dh contains the seconds
-       andb    $0x0f, %al
-       movb    %dh, %ah
-       movb    $0x04, %cl
-       shrb    %cl, %ah
-       aad
-       popw    %cx
-       ret
-
-# Delay is needed after doing I/O
-delay:
-       outb    %al,$0x80
-       ret
-
-# Descriptor tables
-gdt:
-       .word   0, 0, 0, 0                      # dummy
-
-       .word   0, 0, 0, 0                      # unused
-
-       .word   0xFFFF                          # 4Gb - (0x100000*0x1000 = 4Gb)
-       .word   0                               # base address = 0
-       .word   0x9A00                          # code read/exec
-       .word   0x00CF                          # granularity = 4096, 386
-                                               #  (+5th nibble of limit)
-
-       .word   0xFFFF                          # 4Gb - (0x100000*0x1000 = 4Gb)
-       .word   0                               # base address = 0
-       .word   0x9200                          # data read/write
-       .word   0x00CF                          # granularity = 4096, 386
-                                               #  (+5th nibble of limit)
-gdt_end:
-idt_48:
-       .word   0                               # idt limit = 0
-       .word   0, 0                            # idt base = 0L
-gdt_48:
-       .word   gdt_end-gdt-1                   # gdt limit
-       .word   0, 0                            # gdt base (filled in later)
-
-# Include video setup & detection code
-
-#include "../../i386/boot/video.S"
-
-# Setup signature -- must be last
-setup_sig1:    .word   SIG1
-setup_sig2:    .word   SIG2
-
-# After this point, there is some free space which is used by the video mode
-# handling code to store the temporary mode table (not used by the kernel).
-
-modelist:
-
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
diff --git a/arch/x86_64/boot/tools/build.c b/arch/x86_64/boot/tools/build.c
deleted file mode 100644 (file)
index eae8669..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *  Copyright (C) 1997 Martin Mares
- */
-
-/*
- * This file builds a disk-image from three different files:
- *
- * - bootsect: compatibility mbr which prints an error message if
- *             someone tries to boot the kernel directly.
- * - setup: 8086 machine code, sets up system parm
- * - system: 80386 code for actual system
- *
- * It does some checking that all files are of the correct type, and
- * just writes the result to stdout, removing headers and padding to
- * the right amount. It also writes some system data to stderr.
- */
-
-/*
- * Changes by tytso to allow root device specification
- * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
- * Cross compiling fixes by Gertjan van Wingerde, July 1996
- * Rewritten by Martin Mares, April 1997
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <asm/boot.h>
-
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long u32;
-
-#define DEFAULT_MAJOR_ROOT 0
-#define DEFAULT_MINOR_ROOT 0
-
-/* Minimal number of setup sectors (see also bootsect.S) */
-#define SETUP_SECTS 4
-
-byte buf[1024];
-int fd;
-int is_big_kernel;
-
-void die(const char * str, ...)
-{
-       va_list args;
-       va_start(args, str);
-       vfprintf(stderr, str, args);
-       fputc('\n', stderr);
-       exit(1);
-}
-
-void file_open(const char *name)
-{
-       if ((fd = open(name, O_RDONLY, 0)) < 0)
-               die("Unable to open `%s': %m", name);
-}
-
-void usage(void)
-{
-       die("Usage: build [-b] bootsect setup system [rootdev] [> image]");
-}
-
-int main(int argc, char ** argv)
-{
-       unsigned int i, c, sz, setup_sectors;
-       u32 sys_size;
-       byte major_root, minor_root;
-       struct stat sb;
-
-       if (argc > 2 && !strcmp(argv[1], "-b"))
-         {
-           is_big_kernel = 1;
-           argc--, argv++;
-         }
-       if ((argc < 4) || (argc > 5))
-               usage();
-       if (argc > 4) {
-               if (!strcmp(argv[4], "CURRENT")) {
-                       if (stat("/", &sb)) {
-                               perror("/");
-                               die("Couldn't stat /");
-                       }
-                       major_root = major(sb.st_dev);
-                       minor_root = minor(sb.st_dev);
-               } else if (strcmp(argv[4], "FLOPPY")) {
-                       if (stat(argv[4], &sb)) {
-                               perror(argv[4]);
-                               die("Couldn't stat root device.");
-                       }
-                       major_root = major(sb.st_rdev);
-                       minor_root = minor(sb.st_rdev);
-               } else {
-                       major_root = 0;
-                       minor_root = 0;
-               }
-       } else {
-               major_root = DEFAULT_MAJOR_ROOT;
-               minor_root = DEFAULT_MINOR_ROOT;
-       }
-       fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
-
-       file_open(argv[1]);
-       i = read(fd, buf, sizeof(buf));
-       fprintf(stderr,"Boot sector %d bytes.\n",i);
-       if (i != 512)
-               die("Boot block must be exactly 512 bytes");
-       if (buf[510] != 0x55 || buf[511] != 0xaa)
-               die("Boot block hasn't got boot flag (0xAA55)");
-       buf[508] = minor_root;
-       buf[509] = major_root;
-       if (write(1, buf, 512) != 512)
-               die("Write call failed");
-       close (fd);
-
-       file_open(argv[2]);                                 /* Copy the setup code */
-       for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c )
-               if (write(1, buf, c) != c)
-                       die("Write call failed");
-       if (c != 0)
-               die("read-error on `setup'");
-       close (fd);
-
-       setup_sectors = (i + 511) / 512;        /* Pad unused space with zeros */
-       /* for compatibility with ancient versions of LILO. */
-       if (setup_sectors < SETUP_SECTS)
-               setup_sectors = SETUP_SECTS;
-       fprintf(stderr, "Setup is %d bytes.\n", i);
-       memset(buf, 0, sizeof(buf));
-       while (i < setup_sectors * 512) {
-               c = setup_sectors * 512 - i;
-               if (c > sizeof(buf))
-                       c = sizeof(buf);
-               if (write(1, buf, c) != c)
-                       die("Write call failed");
-               i += c;
-       }
-
-       file_open(argv[3]);
-       if (fstat (fd, &sb))
-               die("Unable to stat `%s': %m", argv[3]);
-       sz = sb.st_size;
-       fprintf (stderr, "System is %d kB\n", sz/1024);
-       sys_size = (sz + 15) / 16;
-       if (!is_big_kernel && sys_size > DEF_SYSSIZE)
-               die("System is too big. Try using bzImage or modules.");
-       while (sz > 0) {
-               int l, n;
-
-               l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
-               if ((n=read(fd, buf, l)) != l) {
-                       if (n < 0)
-                               die("Error reading %s: %m", argv[3]);
-                       else
-                               die("%s: Unexpected EOF", argv[3]);
-               }
-               if (write(1, buf, l) != l)
-                       die("Write failed");
-               sz -= l;
-       }
-       close(fd);
-
-       if (lseek(1, 497, SEEK_SET) != 497)                 /* Write sizes to the bootsector */
-               die("Output: seek failed");
-       buf[0] = setup_sectors;
-       if (write(1, buf, 1) != 1)
-               die("Write of setup sector count failed");
-       if (lseek(1, 500, SEEK_SET) != 500)
-               die("Output: seek failed");
-       buf[0] = (sys_size & 0xff);
-       buf[1] = ((sys_size >> 8) & 0xff);
-       buf[2] = ((sys_size >> 16) & 0xff);
-       buf[3] = ((sys_size >> 24) & 0xff);
-       if (write(1, buf, 4) != 4)
-               die("Write of image length failed");
-
-       return 0;                                           /* Everything is OK */
-}
index de1de8a2fd84669e4643585e5119fa7d2e2db594..47f1dc30bf565625c86d96ff4862e685f2a72615 100644 (file)
@@ -44,6 +44,7 @@ obj-$(CONFIG_PCI)             += early-quirks.o
 
 obj-y                          += topology.o
 obj-y                          += intel_cacheinfo.o
+obj-y                          += addon_cpuid_features.o
 obj-y                          += pcspeaker.o
 
 CFLAGS_vsyscall.o              := $(PROFILING) -g0
@@ -55,6 +56,7 @@ cpuid-$(subst m,y,$(CONFIG_X86_CPUID))  += ../../i386/kernel/cpuid.o
 topology-y                     += ../../i386/kernel/topology.o
 microcode-$(subst m,y,$(CONFIG_MICROCODE))  += ../../i386/kernel/microcode.o
 intel_cacheinfo-y              += ../../i386/kernel/cpu/intel_cacheinfo.o
+addon_cpuid_features-y         += ../../i386/kernel/cpu/addon_cpuid_features.o
 quirks-y                       += ../../i386/kernel/quirks.o
 i8237-y                                += ../../i386/kernel/i8237.o
 msr-$(subst m,y,$(CONFIG_X86_MSR))  += ../../i386/kernel/msr.o
index c0749d2479f5b79acb053274f58302f8f4fbec99..a3fd51926cbd0fe0c59185f8a94764505a961560 100644 (file)
@@ -48,10 +48,6 @@ config X86_SPEEDSTEP_CENTRINO
 
          If in doubt, say N.
 
-config X86_SPEEDSTEP_CENTRINO_ACPI
-       bool
-       depends on X86_SPEEDSTEP_CENTRINO
-
 config X86_ACPI_CPUFREQ
        tristate "ACPI Processor P-States driver"
        select CPU_FREQ_TABLE
@@ -73,7 +69,7 @@ comment "shared options"
 config X86_ACPI_CPUFREQ_PROC_INTF
        bool "/proc/acpi/processor/../performance interface (deprecated)"
        depends on PROC_FS
-       depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K8_ACPI
+       depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K8_ACPI
        help
          This enables the deprecated /proc/acpi/processor/../performance
          interface. While it is helpful for debugging, the generic,
index 9f80aad3fe2da40096633bdb0a689f7f0452eb96..90f6315d02d42c062a57d0453b3ab58326a1e6a7 100644 (file)
@@ -22,8 +22,7 @@ EXPORT_SYMBOL(bad_dma_address);
 int iommu_bio_merge __read_mostly = 0;
 EXPORT_SYMBOL(iommu_bio_merge);
 
-int iommu_sac_force __read_mostly = 0;
-EXPORT_SYMBOL(iommu_sac_force);
+static int iommu_sac_force __read_mostly = 0;
 
 int no_iommu __read_mostly;
 #ifdef CONFIG_IOMMU_DEBUG
index eb6524f3ac29b00482800421ed615b674ee453de..33ef718f8cb5ee1e5cbf08c5644a25b592f685ea 100644 (file)
@@ -846,6 +846,8 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
                        c->x86_capability[2] = cpuid_edx(0x80860001);
        }
 
+       init_scattered_cpuid_features(c);
+
        c->apicid = phys_pkg_id(0);
 
        /*
@@ -931,7 +933,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
                "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
                "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
-               "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
+               "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
 
                /* AMD-defined */
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -947,10 +949,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* Other (Linux-defined) */
-               "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
-               "constant_tsc", NULL, NULL,
-               "up", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
+               NULL, NULL, NULL, NULL,
+               "constant_tsc", "up", NULL, "arch_perfmon",
+               "pebs", "bts", NULL, "sync_rdtsc",
+               "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* Intel-defined (#2) */
@@ -961,7 +964,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
                /* VIA/Cyrix/Centaur-defined */
                NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
-               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               "ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
@@ -972,6 +975,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                "osvw", "ibs", NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+               /* Auxiliary (Linux-defined) */
+               "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
        };
        static char *x86_power_flags[] = { 
                "ts",   /* temperature sensor */
index e035f5948199d356a7740d95ac55f21c299594b9..45b6f8a975a152b1e1a9466cd9c64fa61d1a3020 100644 (file)
@@ -37,20 +37,6 @@ verify_cpu:
        pushl   $0                      # Kill any dangerous flags
        popfl
 
-       /* minimum CPUID flags for x86-64 as defined by AMD */
-#define M(x) (1<<(x))
-#define M2(a,b) M(a)|M(b)
-#define M4(a,b,c,d) M(a)|M(b)|M(c)|M(d)
-
-#define SSE_MASK \
-       (M2(X86_FEATURE_XMM,X86_FEATURE_XMM2))
-#define REQUIRED_MASK1 \
-       (M4(X86_FEATURE_FPU,X86_FEATURE_PSE,X86_FEATURE_TSC,X86_FEATURE_MSR)|\
-        M4(X86_FEATURE_PAE,X86_FEATURE_CX8,X86_FEATURE_PGE,X86_FEATURE_CMOV)|\
-        M(X86_FEATURE_FXSR))
-#define REQUIRED_MASK2 \
-       (M(X86_FEATURE_LM - 32))
-
        pushfl                          # standard way to check for cpuid
        popl    %eax
        movl    %eax,%ebx
@@ -79,8 +65,8 @@ verify_cpu:
 verify_cpu_noamd:
        movl    $0x1,%eax               # Does the cpu have what it takes
        cpuid
-       andl    $REQUIRED_MASK1,%edx
-       xorl    $REQUIRED_MASK1,%edx
+       andl    $REQUIRED_MASK0,%edx
+       xorl    $REQUIRED_MASK0,%edx
        jnz     verify_cpu_no_longmode
 
        movl    $0x80000000,%eax        # See if extended cpuid is implemented
@@ -90,8 +76,8 @@ verify_cpu_noamd:
 
        movl    $0x80000001,%eax        # Does the cpu have what it takes
        cpuid
-       andl    $REQUIRED_MASK2,%edx
-       xorl    $REQUIRED_MASK2,%edx
+       andl    $REQUIRED_MASK1,%edx
+       xorl    $REQUIRED_MASK1,%edx
        jnz     verify_cpu_no_longmode
 
 verify_cpu_sse_test:
index 4ca0ab3448d9f3887cd3c64594f0006c71194dfd..07090e9f9bcfef1dc86c9835dee220625a5e0e80 100644 (file)
@@ -1,7 +1,17 @@
 #
-# Cryptographic API Configuration
+# Generic algorithms support
+#
+config XOR_BLOCKS
+       tristate
+
 #
+# async_tx api: hardware offloaded memory transfer/transform support
+#
+source "crypto/async_tx/Kconfig"
 
+#
+# Cryptographic API Configuration
+#
 menu "Cryptographic options"
 
 config CRYPTO
index cce46a1c9dc7ccfea486e92b04a0dd6fec71a28e..0cf17f1ea1513a17ee828d53bea6bd09b56e27d0 100644 (file)
@@ -50,3 +50,9 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
 
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
+
+#
+# generic algorithms and the async_tx api
+#
+obj-$(CONFIG_XOR_BLOCKS) += xor.o
+obj-$(CONFIG_ASYNC_CORE) += async_tx/
diff --git a/crypto/async_tx/Kconfig b/crypto/async_tx/Kconfig
new file mode 100644 (file)
index 0000000..d8fb391
--- /dev/null
@@ -0,0 +1,16 @@
+config ASYNC_CORE
+       tristate
+
+config ASYNC_MEMCPY
+       tristate
+       select ASYNC_CORE
+
+config ASYNC_XOR
+       tristate
+       select ASYNC_CORE
+       select XOR_BLOCKS
+
+config ASYNC_MEMSET
+       tristate
+       select ASYNC_CORE
+
diff --git a/crypto/async_tx/Makefile b/crypto/async_tx/Makefile
new file mode 100644 (file)
index 0000000..27baa7d
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_ASYNC_CORE) += async_tx.o
+obj-$(CONFIG_ASYNC_MEMCPY) += async_memcpy.o
+obj-$(CONFIG_ASYNC_MEMSET) += async_memset.o
+obj-$(CONFIG_ASYNC_XOR) += async_xor.o
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
new file mode 100644 (file)
index 0000000..a973f4e
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * copy offload engine support
+ *
+ * Copyright Â© 2006, Intel Corporation.
+ *
+ *      Dan Williams <dan.j.williams@intel.com>
+ *
+ *      with architecture considerations by:
+ *      Neil Brown <neilb@suse.de>
+ *      Jeff Garzik <jeff@garzik.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/async_tx.h>
+
+/**
+ * async_memcpy - attempt to copy memory with a dma engine.
+ * @dest: destination page
+ * @src: src page
+ * @offset: offset in pages to start transaction
+ * @len: length in bytes
+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK,
+ *     ASYNC_TX_KMAP_SRC, ASYNC_TX_KMAP_DST
+ * @depend_tx: memcpy depends on the result of this transaction
+ * @cb_fn: function to call when the memcpy completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+       unsigned int src_offset, size_t len, enum async_tx_flags flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_param)
+{
+       struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY);
+       struct dma_device *device = chan ? chan->device : NULL;
+       int int_en = cb_fn ? 1 : 0;
+       struct dma_async_tx_descriptor *tx = device ?
+               device->device_prep_dma_memcpy(chan, len,
+               int_en) : NULL;
+
+       if (tx) { /* run the memcpy asynchronously */
+               dma_addr_t addr;
+               enum dma_data_direction dir;
+
+               pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+
+               dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+                       DMA_NONE : DMA_FROM_DEVICE;
+
+               addr = dma_map_page(device->dev, dest, dest_offset, len, dir);
+               tx->tx_set_dest(addr, tx, 0);
+
+               dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+                       DMA_NONE : DMA_TO_DEVICE;
+
+               addr = dma_map_page(device->dev, src, src_offset, len, dir);
+               tx->tx_set_src(addr, tx, 0);
+
+               async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+       } else { /* run the memcpy synchronously */
+               void *dest_buf, *src_buf;
+               pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+
+               /* wait for any prerequisite operations */
+               if (depend_tx) {
+                       /* if ack is already set then we cannot be sure
+                        * we are referring to the correct operation
+                        */
+                       BUG_ON(depend_tx->ack);
+                       if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+                               panic("%s: DMA_ERROR waiting for depend_tx\n",
+                                       __FUNCTION__);
+               }
+
+               if (flags & ASYNC_TX_KMAP_DST)
+                       dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
+               else
+                       dest_buf = page_address(dest) + dest_offset;
+
+               if (flags & ASYNC_TX_KMAP_SRC)
+                       src_buf = kmap_atomic(src, KM_USER0) + src_offset;
+               else
+                       src_buf = page_address(src) + src_offset;
+
+               memcpy(dest_buf, src_buf, len);
+
+               if (flags & ASYNC_TX_KMAP_DST)
+                       kunmap_atomic(dest_buf, KM_USER0);
+
+               if (flags & ASYNC_TX_KMAP_SRC)
+                       kunmap_atomic(src_buf, KM_USER0);
+
+               async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+       }
+
+       return tx;
+}
+EXPORT_SYMBOL_GPL(async_memcpy);
+
+static int __init async_memcpy_init(void)
+{
+       return 0;
+}
+
+static void __exit async_memcpy_exit(void)
+{
+       do { } while (0);
+}
+
+module_init(async_memcpy_init);
+module_exit(async_memcpy_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("asynchronous memcpy api");
+MODULE_LICENSE("GPL");
diff --git a/crypto/async_tx/async_memset.c b/crypto/async_tx/async_memset.c
new file mode 100644 (file)
index 0000000..66ef635
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * memory fill offload engine support
+ *
+ * Copyright Â© 2006, Intel Corporation.
+ *
+ *      Dan Williams <dan.j.williams@intel.com>
+ *
+ *      with architecture considerations by:
+ *      Neil Brown <neilb@suse.de>
+ *      Jeff Garzik <jeff@garzik.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/async_tx.h>
+
+/**
+ * async_memset - attempt to fill memory with a dma engine.
+ * @dest: destination page
+ * @val: fill value
+ * @offset: offset in pages to start transaction
+ * @len: length in bytes
+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: memset depends on the result of this transaction
+ * @cb_fn: function to call when the memcpy completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_memset(struct page *dest, int val, unsigned int offset,
+       size_t len, enum async_tx_flags flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_param)
+{
+       struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET);
+       struct dma_device *device = chan ? chan->device : NULL;
+       int int_en = cb_fn ? 1 : 0;
+       struct dma_async_tx_descriptor *tx = device ?
+               device->device_prep_dma_memset(chan, val, len,
+                       int_en) : NULL;
+
+       if (tx) { /* run the memset asynchronously */
+               dma_addr_t dma_addr;
+               enum dma_data_direction dir;
+
+               pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+               dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+                       DMA_NONE : DMA_FROM_DEVICE;
+
+               dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
+               tx->tx_set_dest(dma_addr, tx, 0);
+
+               async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+       } else { /* run the memset synchronously */
+               void *dest_buf;
+               pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+
+               dest_buf = (void *) (((char *) page_address(dest)) + offset);
+
+               /* wait for any prerequisite operations */
+               if (depend_tx) {
+                       /* if ack is already set then we cannot be sure
+                        * we are referring to the correct operation
+                        */
+                       BUG_ON(depend_tx->ack);
+                       if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+                               panic("%s: DMA_ERROR waiting for depend_tx\n",
+                                       __FUNCTION__);
+               }
+
+               memset(dest_buf, val, len);
+
+               async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+       }
+
+       return tx;
+}
+EXPORT_SYMBOL_GPL(async_memset);
+
+static int __init async_memset_init(void)
+{
+       return 0;
+}
+
+static void __exit async_memset_exit(void)
+{
+       do { } while (0);
+}
+
+module_init(async_memset_init);
+module_exit(async_memset_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("asynchronous memset api");
+MODULE_LICENSE("GPL");
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
new file mode 100644 (file)
index 0000000..0350071
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * core routines for the asynchronous memory transfer/transform api
+ *
+ * Copyright Â© 2006, Intel Corporation.
+ *
+ *     Dan Williams <dan.j.williams@intel.com>
+ *
+ *     with architecture considerations by:
+ *     Neil Brown <neilb@suse.de>
+ *     Jeff Garzik <jeff@garzik.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/async_tx.h>
+
+#ifdef CONFIG_DMA_ENGINE
+static enum dma_state_client
+dma_channel_add_remove(struct dma_client *client,
+       struct dma_chan *chan, enum dma_state state);
+
+static struct dma_client async_tx_dma = {
+       .event_callback = dma_channel_add_remove,
+       /* .cap_mask == 0 defaults to all channels */
+};
+
+/**
+ * dma_cap_mask_all - enable iteration over all operation types
+ */
+static dma_cap_mask_t dma_cap_mask_all;
+
+/**
+ * chan_ref_percpu - tracks channel allocations per core/opertion
+ */
+struct chan_ref_percpu {
+       struct dma_chan_ref *ref;
+};
+
+static int channel_table_initialized;
+static struct chan_ref_percpu *channel_table[DMA_TX_TYPE_END];
+
+/**
+ * async_tx_lock - protect modification of async_tx_master_list and serialize
+ *     rebalance operations
+ */
+static spinlock_t async_tx_lock;
+
+static struct list_head
+async_tx_master_list = LIST_HEAD_INIT(async_tx_master_list);
+
+/* async_tx_issue_pending_all - start all transactions on all channels */
+void async_tx_issue_pending_all(void)
+{
+       struct dma_chan_ref *ref;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+               ref->chan->device->device_issue_pending(ref->chan);
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(async_tx_issue_pending_all);
+
+/* dma_wait_for_async_tx - spin wait for a transcation to complete
+ * @tx: transaction to wait on
+ */
+enum dma_status
+dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+{
+       enum dma_status status;
+       struct dma_async_tx_descriptor *iter;
+
+       if (!tx)
+               return DMA_SUCCESS;
+
+       /* poll through the dependency chain, return when tx is complete */
+       do {
+               iter = tx;
+               while (iter->cookie == -EBUSY)
+                       iter = iter->parent;
+
+               status = dma_sync_wait(iter->chan, iter->cookie);
+       } while (status == DMA_IN_PROGRESS || (iter != tx));
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
+
+/* async_tx_run_dependencies - helper routine for dma drivers to process
+ *     (start) dependent operations on their target channel
+ * @tx: transaction with dependencies
+ */
+void
+async_tx_run_dependencies(struct dma_async_tx_descriptor *tx)
+{
+       struct dma_async_tx_descriptor *dep_tx, *_dep_tx;
+       struct dma_device *dev;
+       struct dma_chan *chan;
+
+       list_for_each_entry_safe(dep_tx, _dep_tx, &tx->depend_list,
+               depend_node) {
+               chan = dep_tx->chan;
+               dev = chan->device;
+               /* we can't depend on ourselves */
+               BUG_ON(chan == tx->chan);
+               list_del(&dep_tx->depend_node);
+               tx->tx_submit(dep_tx);
+
+               /* we need to poke the engine as client code does not
+                * know about dependency submission events
+                */
+               dev->device_issue_pending(chan);
+       }
+}
+EXPORT_SYMBOL_GPL(async_tx_run_dependencies);
+
+static void
+free_dma_chan_ref(struct rcu_head *rcu)
+{
+       struct dma_chan_ref *ref;
+       ref = container_of(rcu, struct dma_chan_ref, rcu);
+       kfree(ref);
+}
+
+static void
+init_dma_chan_ref(struct dma_chan_ref *ref, struct dma_chan *chan)
+{
+       INIT_LIST_HEAD(&ref->node);
+       INIT_RCU_HEAD(&ref->rcu);
+       ref->chan = chan;
+       atomic_set(&ref->count, 0);
+}
+
+/**
+ * get_chan_ref_by_cap - returns the nth channel of the given capability
+ *     defaults to returning the channel with the desired capability and the
+ *     lowest reference count if the index can not be satisfied
+ * @cap: capability to match
+ * @index: nth channel desired, passing -1 has the effect of forcing the
+ *  default return value
+ */
+static struct dma_chan_ref *
+get_chan_ref_by_cap(enum dma_transaction_type cap, int index)
+{
+       struct dma_chan_ref *ret_ref = NULL, *min_ref = NULL, *ref;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+               if (dma_has_cap(cap, ref->chan->device->cap_mask)) {
+                       if (!min_ref)
+                               min_ref = ref;
+                       else if (atomic_read(&ref->count) <
+                               atomic_read(&min_ref->count))
+                               min_ref = ref;
+
+                       if (index-- == 0) {
+                               ret_ref = ref;
+                               break;
+                       }
+               }
+       rcu_read_unlock();
+
+       if (!ret_ref)
+               ret_ref = min_ref;
+
+       if (ret_ref)
+               atomic_inc(&ret_ref->count);
+
+       return ret_ref;
+}
+
+/**
+ * async_tx_rebalance - redistribute the available channels, optimize
+ * for cpu isolation in the SMP case, and opertaion isolation in the
+ * uniprocessor case
+ */
+static void async_tx_rebalance(void)
+{
+       int cpu, cap, cpu_idx = 0;
+       unsigned long flags;
+
+       if (!channel_table_initialized)
+               return;
+
+       spin_lock_irqsave(&async_tx_lock, flags);
+
+       /* undo the last distribution */
+       for_each_dma_cap_mask(cap, dma_cap_mask_all)
+               for_each_possible_cpu(cpu) {
+                       struct dma_chan_ref *ref =
+                               per_cpu_ptr(channel_table[cap], cpu)->ref;
+                       if (ref) {
+                               atomic_set(&ref->count, 0);
+                               per_cpu_ptr(channel_table[cap], cpu)->ref =
+                                                                       NULL;
+                       }
+               }
+
+       for_each_dma_cap_mask(cap, dma_cap_mask_all)
+               for_each_online_cpu(cpu) {
+                       struct dma_chan_ref *new;
+                       if (NR_CPUS > 1)
+                               new = get_chan_ref_by_cap(cap, cpu_idx++);
+                       else
+                               new = get_chan_ref_by_cap(cap, -1);
+
+                       per_cpu_ptr(channel_table[cap], cpu)->ref = new;
+               }
+
+       spin_unlock_irqrestore(&async_tx_lock, flags);
+}
+
+static enum dma_state_client
+dma_channel_add_remove(struct dma_client *client,
+       struct dma_chan *chan, enum dma_state state)
+{
+       unsigned long found, flags;
+       struct dma_chan_ref *master_ref, *ref;
+       enum dma_state_client ack = DMA_DUP; /* default: take no action */
+
+       switch (state) {
+       case DMA_RESOURCE_AVAILABLE:
+               found = 0;
+               rcu_read_lock();
+               list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+                       if (ref->chan == chan) {
+                               found = 1;
+                               break;
+                       }
+               rcu_read_unlock();
+
+               pr_debug("async_tx: dma resource available [%s]\n",
+                       found ? "old" : "new");
+
+               if (!found)
+                       ack = DMA_ACK;
+               else
+                       break;
+
+               /* add the channel to the generic management list */
+               master_ref = kmalloc(sizeof(*master_ref), GFP_KERNEL);
+               if (master_ref) {
+                       /* keep a reference until async_tx is unloaded */
+                       dma_chan_get(chan);
+                       init_dma_chan_ref(master_ref, chan);
+                       spin_lock_irqsave(&async_tx_lock, flags);
+                       list_add_tail_rcu(&master_ref->node,
+                               &async_tx_master_list);
+                       spin_unlock_irqrestore(&async_tx_lock,
+                               flags);
+               } else {
+                       printk(KERN_WARNING "async_tx: unable to create"
+                               " new master entry in response to"
+                               " a DMA_RESOURCE_ADDED event"
+                               " (-ENOMEM)\n");
+                       return 0;
+               }
+
+               async_tx_rebalance();
+               break;
+       case DMA_RESOURCE_REMOVED:
+               found = 0;
+               spin_lock_irqsave(&async_tx_lock, flags);
+               list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+                       if (ref->chan == chan) {
+                               /* permit backing devices to go away */
+                               dma_chan_put(ref->chan);
+                               list_del_rcu(&ref->node);
+                               call_rcu(&ref->rcu, free_dma_chan_ref);
+                               found = 1;
+                               break;
+                       }
+               spin_unlock_irqrestore(&async_tx_lock, flags);
+
+               pr_debug("async_tx: dma resource removed [%s]\n",
+                       found ? "ours" : "not ours");
+
+               if (found)
+                       ack = DMA_ACK;
+               else
+                       break;
+
+               async_tx_rebalance();
+               break;
+       case DMA_RESOURCE_SUSPEND:
+       case DMA_RESOURCE_RESUME:
+               printk(KERN_WARNING "async_tx: does not support dma channel"
+                       " suspend/resume\n");
+               break;
+       default:
+               BUG();
+       }
+
+       return ack;
+}
+
+static int __init
+async_tx_init(void)
+{
+       enum dma_transaction_type cap;
+
+       spin_lock_init(&async_tx_lock);
+       bitmap_fill(dma_cap_mask_all.bits, DMA_TX_TYPE_END);
+
+       /* an interrupt will never be an explicit operation type.
+        * clearing this bit prevents allocation to a slot in 'channel_table'
+        */
+       clear_bit(DMA_INTERRUPT, dma_cap_mask_all.bits);
+
+       for_each_dma_cap_mask(cap, dma_cap_mask_all) {
+               channel_table[cap] = alloc_percpu(struct chan_ref_percpu);
+               if (!channel_table[cap])
+                       goto err;
+       }
+
+       channel_table_initialized = 1;
+       dma_async_client_register(&async_tx_dma);
+       dma_async_client_chan_request(&async_tx_dma);
+
+       printk(KERN_INFO "async_tx: api initialized (async)\n");
+
+       return 0;
+err:
+       printk(KERN_ERR "async_tx: initialization failure\n");
+
+       while (--cap >= 0)
+               free_percpu(channel_table[cap]);
+
+       return 1;
+}
+
+static void __exit async_tx_exit(void)
+{
+       enum dma_transaction_type cap;
+
+       channel_table_initialized = 0;
+
+       for_each_dma_cap_mask(cap, dma_cap_mask_all)
+               if (channel_table[cap])
+                       free_percpu(channel_table[cap]);
+
+       dma_async_client_unregister(&async_tx_dma);
+}
+
+/**
+ * async_tx_find_channel - find a channel to carry out the operation or let
+ *     the transaction execute synchronously
+ * @depend_tx: transaction dependency
+ * @tx_type: transaction type
+ */
+struct dma_chan *
+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+       enum dma_transaction_type tx_type)
+{
+       /* see if we can keep the chain on one channel */
+       if (depend_tx &&
+               dma_has_cap(tx_type, depend_tx->chan->device->cap_mask))
+               return depend_tx->chan;
+       else if (likely(channel_table_initialized)) {
+               struct dma_chan_ref *ref;
+               int cpu = get_cpu();
+               ref = per_cpu_ptr(channel_table[tx_type], cpu)->ref;
+               put_cpu();
+               return ref ? ref->chan : NULL;
+       } else
+               return NULL;
+}
+EXPORT_SYMBOL_GPL(async_tx_find_channel);
+#else
+static int __init async_tx_init(void)
+{
+       printk(KERN_INFO "async_tx: api initialized (sync-only)\n");
+       return 0;
+}
+
+static void __exit async_tx_exit(void)
+{
+       do { } while (0);
+}
+#endif
+
+void
+async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+       enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_param)
+{
+       tx->callback = cb_fn;
+       tx->callback_param = cb_param;
+
+       /* set this new tx to run after depend_tx if:
+        * 1/ a dependency exists (depend_tx is !NULL)
+        * 2/ the tx can not be submitted to the current channel
+        */
+       if (depend_tx && depend_tx->chan != chan) {
+               /* if ack is already set then we cannot be sure
+                * we are referring to the correct operation
+                */
+               BUG_ON(depend_tx->ack);
+
+               tx->parent = depend_tx;
+               spin_lock_bh(&depend_tx->lock);
+               list_add_tail(&tx->depend_node, &depend_tx->depend_list);
+               if (depend_tx->cookie == 0) {
+                       struct dma_chan *dep_chan = depend_tx->chan;
+                       struct dma_device *dep_dev = dep_chan->device;
+                       dep_dev->device_dependency_added(dep_chan);
+               }
+               spin_unlock_bh(&depend_tx->lock);
+
+               /* schedule an interrupt to trigger the channel switch */
+               async_trigger_callback(ASYNC_TX_ACK, depend_tx, NULL, NULL);
+       } else {
+               tx->parent = NULL;
+               tx->tx_submit(tx);
+       }
+
+       if (flags & ASYNC_TX_ACK)
+               async_tx_ack(tx);
+
+       if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
+               async_tx_ack(depend_tx);
+}
+EXPORT_SYMBOL_GPL(async_tx_submit);
+
+/**
+ * async_trigger_callback - schedules the callback function to be run after
+ * any dependent operations have been completed.
+ * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: 'callback' requires the completion of this transaction
+ * @cb_fn: function to call after depend_tx completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_trigger_callback(enum async_tx_flags flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_param)
+{
+       struct dma_chan *chan;
+       struct dma_device *device;
+       struct dma_async_tx_descriptor *tx;
+
+       if (depend_tx) {
+               chan = depend_tx->chan;
+               device = chan->device;
+
+               /* see if we can schedule an interrupt
+                * otherwise poll for completion
+                */
+               if (device && !dma_has_cap(DMA_INTERRUPT, device->cap_mask))
+                       device = NULL;
+
+               tx = device ? device->device_prep_dma_interrupt(chan) : NULL;
+       } else
+               tx = NULL;
+
+       if (tx) {
+               pr_debug("%s: (async)\n", __FUNCTION__);
+
+               async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+       } else {
+               pr_debug("%s: (sync)\n", __FUNCTION__);
+
+               /* wait for any prerequisite operations */
+               if (depend_tx) {
+                       /* if ack is already set then we cannot be sure
+                        * we are referring to the correct operation
+                        */
+                       BUG_ON(depend_tx->ack);
+                       if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+                               panic("%s: DMA_ERROR waiting for depend_tx\n",
+                                       __FUNCTION__);
+               }
+
+               async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+       }
+
+       return tx;
+}
+EXPORT_SYMBOL_GPL(async_trigger_callback);
+
+module_init(async_tx_init);
+module_exit(async_tx_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Asynchronous Bulk Memory Transactions API");
+MODULE_LICENSE("GPL");
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
new file mode 100644 (file)
index 0000000..2575f67
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * xor offload engine api
+ *
+ * Copyright Â© 2006, Intel Corporation.
+ *
+ *      Dan Williams <dan.j.williams@intel.com>
+ *
+ *      with architecture considerations by:
+ *      Neil Brown <neilb@suse.de>
+ *      Jeff Garzik <jeff@garzik.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/raid/xor.h>
+#include <linux/async_tx.h>
+
+static void
+do_async_xor(struct dma_async_tx_descriptor *tx, struct dma_device *device,
+       struct dma_chan *chan, struct page *dest, struct page **src_list,
+       unsigned int offset, unsigned int src_cnt, size_t len,
+       enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_param)
+{
+       dma_addr_t dma_addr;
+       enum dma_data_direction dir;
+       int i;
+
+       pr_debug("%s: len: %zu\n", __FUNCTION__, len);
+
+       dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+               DMA_NONE : DMA_FROM_DEVICE;
+
+       dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
+       tx->tx_set_dest(dma_addr, tx, 0);
+
+       dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+               DMA_NONE : DMA_TO_DEVICE;
+
+       for (i = 0; i < src_cnt; i++) {
+               dma_addr = dma_map_page(device->dev, src_list[i],
+                       offset, len, dir);
+               tx->tx_set_src(dma_addr, tx, i);
+       }
+
+       async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+}
+
+static void
+do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
+       unsigned int src_cnt, size_t len, enum async_tx_flags flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_param)
+{
+       void *_dest;
+       int i;
+
+       pr_debug("%s: len: %zu\n", __FUNCTION__, len);
+
+       /* reuse the 'src_list' array to convert to buffer pointers */
+       for (i = 0; i < src_cnt; i++)
+               src_list[i] = (struct page *)
+                       (page_address(src_list[i]) + offset);
+
+       /* set destination address */
+       _dest = page_address(dest) + offset;
+
+       if (flags & ASYNC_TX_XOR_ZERO_DST)
+               memset(_dest, 0, len);
+
+       xor_blocks(src_cnt, len, _dest,
+               (void **) src_list);
+
+       async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+}
+
+/**
+ * async_xor - attempt to xor a set of blocks with a dma engine.
+ *     xor_blocks always uses the dest as a source so the ASYNC_TX_XOR_ZERO_DST
+ *     flag must be set to not include dest data in the calculation.  The
+ *     assumption with dma eninges is that they only use the destination
+ *     buffer as a source when it is explicity specified in the source list.
+ * @dest: destination page
+ * @src_list: array of source pages (if the dest is also a source it must be
+ *     at index zero).  The contents of this array may be overwritten.
+ * @offset: offset in pages to start transaction
+ * @src_cnt: number of source pages
+ * @len: length in bytes
+ * @flags: ASYNC_TX_XOR_ZERO_DST, ASYNC_TX_XOR_DROP_DEST,
+ *     ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: xor depends on the result of this transaction.
+ * @cb_fn: function to call when the xor completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_xor(struct page *dest, struct page **src_list, unsigned int offset,
+       int src_cnt, size_t len, enum async_tx_flags flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_param)
+{
+       struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR);
+       struct dma_device *device = chan ? chan->device : NULL;
+       struct dma_async_tx_descriptor *tx = NULL;
+       dma_async_tx_callback _cb_fn;
+       void *_cb_param;
+       unsigned long local_flags;
+       int xor_src_cnt;
+       int i = 0, src_off = 0, int_en;
+
+       BUG_ON(src_cnt <= 1);
+
+       while (src_cnt) {
+               local_flags = flags;
+               if (device) { /* run the xor asynchronously */
+                       xor_src_cnt = min(src_cnt, device->max_xor);
+                       /* if we are submitting additional xors
+                        * only set the callback on the last transaction
+                        */
+                       if (src_cnt > xor_src_cnt) {
+                               local_flags &= ~ASYNC_TX_ACK;
+                               _cb_fn = NULL;
+                               _cb_param = NULL;
+                       } else {
+                               _cb_fn = cb_fn;
+                               _cb_param = cb_param;
+                       }
+
+                       int_en = _cb_fn ? 1 : 0;
+
+                       tx = device->device_prep_dma_xor(
+                               chan, xor_src_cnt, len, int_en);
+
+                       if (tx) {
+                               do_async_xor(tx, device, chan, dest,
+                               &src_list[src_off], offset, xor_src_cnt, len,
+                               local_flags, depend_tx, _cb_fn,
+                               _cb_param);
+                       } else /* fall through */
+                               goto xor_sync;
+               } else { /* run the xor synchronously */
+xor_sync:
+                       /* in the sync case the dest is an implied source
+                        * (assumes the dest is at the src_off index)
+                        */
+                       if (flags & ASYNC_TX_XOR_DROP_DST) {
+                               src_cnt--;
+                               src_off++;
+                       }
+
+                       /* process up to 'MAX_XOR_BLOCKS' sources */
+                       xor_src_cnt = min(src_cnt, MAX_XOR_BLOCKS);
+
+                       /* if we are submitting additional xors
+                        * only set the callback on the last transaction
+                        */
+                       if (src_cnt > xor_src_cnt) {
+                               local_flags &= ~ASYNC_TX_ACK;
+                               _cb_fn = NULL;
+                               _cb_param = NULL;
+                       } else {
+                               _cb_fn = cb_fn;
+                               _cb_param = cb_param;
+                       }
+
+                       /* wait for any prerequisite operations */
+                       if (depend_tx) {
+                               /* if ack is already set then we cannot be sure
+                                * we are referring to the correct operation
+                                */
+                               BUG_ON(depend_tx->ack);
+                               if (dma_wait_for_async_tx(depend_tx) ==
+                                       DMA_ERROR)
+                                       panic("%s: DMA_ERROR waiting for "
+                                               "depend_tx\n",
+                                               __FUNCTION__);
+                       }
+
+                       do_sync_xor(dest, &src_list[src_off], offset,
+                               xor_src_cnt, len, local_flags, depend_tx,
+                               _cb_fn, _cb_param);
+               }
+
+               /* the previous tx is hidden from the client,
+                * so ack it
+                */
+               if (i && depend_tx)
+                       async_tx_ack(depend_tx);
+
+               depend_tx = tx;
+
+               if (src_cnt > xor_src_cnt) {
+                       /* drop completed sources */
+                       src_cnt -= xor_src_cnt;
+                       src_off += xor_src_cnt;
+
+                       /* unconditionally preserve the destination */
+                       flags &= ~ASYNC_TX_XOR_ZERO_DST;
+
+                       /* use the intermediate result a source, but remember
+                        * it's dropped, because it's implied, in the sync case
+                        */
+                       src_list[--src_off] = dest;
+                       src_cnt++;
+                       flags |= ASYNC_TX_XOR_DROP_DST;
+               } else
+                       src_cnt = 0;
+               i++;
+       }
+
+       return tx;
+}
+EXPORT_SYMBOL_GPL(async_xor);
+
+static int page_is_zero(struct page *p, unsigned int offset, size_t len)
+{
+       char *a = page_address(p) + offset;
+       return ((*(u32 *) a) == 0 &&
+               memcmp(a, a + 4, len - 4) == 0);
+}
+
+/**
+ * async_xor_zero_sum - attempt a xor parity check with a dma engine.
+ * @dest: destination page used if the xor is performed synchronously
+ * @src_list: array of source pages.  The dest page must be listed as a source
+ *     at index zero.  The contents of this array may be overwritten.
+ * @offset: offset in pages to start transaction
+ * @src_cnt: number of source pages
+ * @len: length in bytes
+ * @result: 0 if sum == 0 else non-zero
+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: xor depends on the result of this transaction.
+ * @cb_fn: function to call when the xor completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_xor_zero_sum(struct page *dest, struct page **src_list,
+       unsigned int offset, int src_cnt, size_t len,
+       u32 *result, enum async_tx_flags flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_param)
+{
+       struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM);
+       struct dma_device *device = chan ? chan->device : NULL;
+       int int_en = cb_fn ? 1 : 0;
+       struct dma_async_tx_descriptor *tx = device ?
+               device->device_prep_dma_zero_sum(chan, src_cnt, len, result,
+                       int_en) : NULL;
+       int i;
+
+       BUG_ON(src_cnt <= 1);
+
+       if (tx) {
+               dma_addr_t dma_addr;
+               enum dma_data_direction dir;
+
+               pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+
+               dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+                       DMA_NONE : DMA_TO_DEVICE;
+
+               for (i = 0; i < src_cnt; i++) {
+                       dma_addr = dma_map_page(device->dev, src_list[i],
+                               offset, len, dir);
+                       tx->tx_set_src(dma_addr, tx, i);
+               }
+
+               async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+       } else {
+               unsigned long xor_flags = flags;
+
+               pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+
+               xor_flags |= ASYNC_TX_XOR_DROP_DST;
+               xor_flags &= ~ASYNC_TX_ACK;
+
+               tx = async_xor(dest, src_list, offset, src_cnt, len, xor_flags,
+                       depend_tx, NULL, NULL);
+
+               if (tx) {
+                       if (dma_wait_for_async_tx(tx) == DMA_ERROR)
+                               panic("%s: DMA_ERROR waiting for tx\n",
+                                       __FUNCTION__);
+                       async_tx_ack(tx);
+               }
+
+               *result = page_is_zero(dest, offset, len) ? 0 : 1;
+
+               tx = NULL;
+
+               async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+       }
+
+       return tx;
+}
+EXPORT_SYMBOL_GPL(async_xor_zero_sum);
+
+static int __init async_xor_init(void)
+{
+       return 0;
+}
+
+static void __exit async_xor_exit(void)
+{
+       do { } while (0);
+}
+
+module_init(async_xor_init);
+module_exit(async_xor_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("asynchronous xor/xor-zero-sum api");
+MODULE_LICENSE("GPL");
similarity index 69%
rename from drivers/md/xor.c
rename to crypto/xor.c
index 324897c4be4ed04cac7404f008cf17ca0c0f5dbc..b2e6db075e4993eac4fcffb9004b82ee4a0bca71 100644 (file)
 static struct xor_block_template *active_template;
 
 void
-xor_block(unsigned int count, unsigned int bytes, void **ptr)
+xor_blocks(unsigned int src_count, unsigned int bytes, void *dest, void **srcs)
 {
-       unsigned long *p0, *p1, *p2, *p3, *p4;
+       unsigned long *p1, *p2, *p3, *p4;
 
-       p0 = (unsigned long *) ptr[0];
-       p1 = (unsigned long *) ptr[1];
-       if (count == 2) {
-               active_template->do_2(bytes, p0, p1);
+       p1 = (unsigned long *) srcs[0];
+       if (src_count == 1) {
+               active_template->do_2(bytes, dest, p1);
                return;
        }
 
-       p2 = (unsigned long *) ptr[2];
-       if (count == 3) {
-               active_template->do_3(bytes, p0, p1, p2);
+       p2 = (unsigned long *) srcs[1];
+       if (src_count == 2) {
+               active_template->do_3(bytes, dest, p1, p2);
                return;
        }
 
-       p3 = (unsigned long *) ptr[3];
-       if (count == 4) {
-               active_template->do_4(bytes, p0, p1, p2, p3);
+       p3 = (unsigned long *) srcs[2];
+       if (src_count == 3) {
+               active_template->do_4(bytes, dest, p1, p2, p3);
                return;
        }
 
-       p4 = (unsigned long *) ptr[4];
-       active_template->do_5(bytes, p0, p1, p2, p3, p4);
+       p4 = (unsigned long *) srcs[3];
+       active_template->do_5(bytes, dest, p1, p2, p3, p4);
 }
+EXPORT_SYMBOL(xor_blocks);
 
 /* Set of all registered templates.  */
 static struct xor_block_template *template_list;
@@ -78,7 +78,7 @@ do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
                now = jiffies;
                count = 0;
                while (jiffies == now) {
-                       mb();
+                       mb(); /* prevent loop optimzation */
                        tmpl->do_2(BENCH_SIZE, b1, b2);
                        mb();
                        count++;
@@ -91,26 +91,26 @@ do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
        speed = max * (HZ * BENCH_SIZE / 1024);
        tmpl->speed = speed;
 
-       printk("   %-10s: %5d.%03d MB/sec\n", tmpl->name,
+       printk(KERN_INFO "   %-10s: %5d.%03d MB/sec\n", tmpl->name,
               speed / 1000, speed % 1000);
 }
 
-static int
-calibrate_xor_block(void)
+static int __init
+calibrate_xor_blocks(void)
 {
        void *b1, *b2;
        struct xor_block_template *f, *fastest;
 
        b1 = (void *) __get_free_pages(GFP_KERNEL, 2);
-       if (! b1) {
-               printk("raid5: Yikes!  No memory available.\n");
+       if (!b1) {
+               printk(KERN_WARNING "xor: Yikes!  No memory available.\n");
                return -ENOMEM;
        }
        b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE;
 
        /*
-        * If this arch/cpu has a short-circuited selection, don't loop through all
-        * the possible functions, just test the best one
+        * If this arch/cpu has a short-circuited selection, don't loop through
+        * all the possible functions, just test the best one
         */
 
        fastest = NULL;
@@ -122,11 +122,12 @@ calibrate_xor_block(void)
 #define xor_speed(templ)       do_xor_speed((templ), b1, b2)
 
        if (fastest) {
-               printk(KERN_INFO "raid5: automatically using best checksumming function: %s\n",
+               printk(KERN_INFO "xor: automatically using best "
+                       "checksumming function: %s\n",
                        fastest->name);
                xor_speed(fastest);
        } else {
-               printk(KERN_INFO "raid5: measuring checksumming speed\n");
+               printk(KERN_INFO "xor: measuring software checksum speed\n");
                XOR_TRY_TEMPLATES;
                fastest = template_list;
                for (f = fastest; f; f = f->next)
@@ -134,7 +135,7 @@ calibrate_xor_block(void)
                                fastest = f;
        }
 
-       printk("raid5: using function: %s (%d.%03d MB/sec)\n",
+       printk(KERN_INFO "xor: using function: %s (%d.%03d MB/sec)\n",
               fastest->name, fastest->speed / 1000, fastest->speed % 1000);
 
 #undef xor_speed
@@ -147,8 +148,8 @@ calibrate_xor_block(void)
 
 static __exit void xor_exit(void) { }
 
-EXPORT_SYMBOL(xor_block);
 MODULE_LICENSE("GPL");
 
-module_init(calibrate_xor_block);
+/* when built-in xor.o must initialize before drivers/md/md.o */
+core_initcall(calibrate_xor_blocks);
 module_exit(xor_exit);
index f7de02a6f497a5d61752dff2a413a7c7b4c9f43a..e1ca86dfdd661fa2a53fbf78d3207296795ea165 100644 (file)
@@ -115,7 +115,6 @@ struct acpi_processor_errata errata __read_mostly;
 
 static int acpi_processor_errata_piix4(struct pci_dev *dev)
 {
-       u8 rev = 0;
        u8 value1 = 0;
        u8 value2 = 0;
 
@@ -127,9 +126,7 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
         * Note that 'dev' references the PIIX4 ACPI Controller.
         */
 
-       pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
-       switch (rev) {
+       switch (dev->revision) {
        case 0:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
                break;
@@ -147,7 +144,7 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
                break;
        }
 
-       switch (rev) {
+       switch (dev->revision) {
 
        case 0:         /* PIIX4 A-step */
        case 1:         /* PIIX4 B-step */
index 4ad8675f5a160175e61229220340d4dc0a353037..d8046a113c371ce0dc820f113fbbbb51261fbfcb 100644 (file)
@@ -309,7 +309,7 @@ config PATA_HPT3X2N
          If unsure, say N.
 
 config PATA_HPT3X3
-       tristate "HPT 343/363 PATA support (Experimental)"
+       tristate "HPT 343/363 PATA support"
        depends on PCI
        help
          This option enables support for the HPT 343/363
@@ -317,6 +317,14 @@ config PATA_HPT3X3
 
          If unsure, say N.
 
+config PATA_HPT3X3_DMA
+       bool "HPT 343/363 DMA support (Experimental)"
+       depends on PATA_HPT3X3
+       help
+         This option enables DMA support for the HPT343/363
+         controllers. Enable with care as there are still some
+         problems with DMA on this chipset.
+
 config PATA_ISAPNP
        tristate "ISA Plug and Play PATA support (Experimental)"
        depends on EXPERIMENTAL && ISAPNP
index 6a3bfef58e13ed716ae1d22792da6f15a4b644db..d9fa329fd157741f12b83be996e8b7d419052044 100644 (file)
@@ -414,7 +414,7 @@ static const struct piix_map_db ich6m_map_db = {
         */
        .map = {
                /* PM   PS   SM   SS       MAP */
-               {  P0,  P2,  RV,  RV }, /* 00b */
+               {  P0,  P2,  NA,  NA }, /* 00b */
                { IDE, IDE,  P1,  P3 }, /* 01b */
                {  P0,  P2, IDE, IDE }, /* 10b */
                {  RV,  RV,  RV,  RV },
@@ -928,20 +928,18 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
 {
        struct pci_dev *pdev = NULL;
        u16 cfg;
-       u8 rev;
        int no_piix_dma = 0;
 
        while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL)
        {
                /* Look for 450NX PXB. Check for problem configurations
                   A PCI quirk checks bit 6 already */
-               pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
                pci_read_config_word(pdev, 0x41, &cfg);
                /* Only on the original revision: IDE DMA can hang */
-               if (rev == 0x00)
+               if (pdev->revision == 0x00)
                        no_piix_dma = 1;
                /* On all revisions below 5 PXB bus lock must be disabled for IDE */
-               else if (cfg & (1<<14) && rev < 5)
+               else if (cfg & (1<<14) && pdev->revision < 5)
                        no_piix_dma = 2;
        }
        if (no_piix_dma)
index 5b25311ba885f8bc192ed4d6d6fdeaa9a8cbb7b8..88e2dd0983b536cc31c3dfd6d44ffafa1f2854fc 100644 (file)
@@ -71,6 +71,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
                                        u16 heads, u16 sectors);
 static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
 static void ata_dev_xfermask(struct ata_device *dev);
+static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
 
 unsigned int ata_print_id = 1;
 static struct workqueue_struct *ata_wq;
@@ -1283,18 +1284,11 @@ static unsigned int ata_id_xfermask(const u16 *id)
 void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
                         unsigned long delay)
 {
-       int rc;
-
-       if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK)
-               return;
-
        PREPARE_DELAYED_WORK(&ap->port_task, fn);
        ap->port_task_data = data;
 
-       rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
-
-       /* rc == 0 means that another user is using port task */
-       WARN_ON(rc == 0);
+       /* may fail if ata_port_flush_task() in progress */
+       queue_delayed_work(ata_wq, &ap->port_task, delay);
 }
 
 /**
@@ -1309,32 +1303,9 @@ void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
  */
 void ata_port_flush_task(struct ata_port *ap)
 {
-       unsigned long flags;
-
        DPRINTK("ENTER\n");
 
-       spin_lock_irqsave(ap->lock, flags);
-       ap->pflags |= ATA_PFLAG_FLUSH_PORT_TASK;
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       DPRINTK("flush #1\n");
-       cancel_work_sync(&ap->port_task.work); /* akpm: seems unneeded */
-
-       /*
-        * At this point, if a task is running, it's guaranteed to see
-        * the FLUSH flag; thus, it will never queue pio tasks again.
-        * Cancel and flush.
-        */
-       if (!cancel_delayed_work(&ap->port_task)) {
-               if (ata_msg_ctl(ap))
-                       ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n",
-                                       __FUNCTION__);
-               cancel_work_sync(&ap->port_task.work);
-       }
-
-       spin_lock_irqsave(ap->lock, flags);
-       ap->pflags &= ~ATA_PFLAG_FLUSH_PORT_TASK;
-       spin_unlock_irqrestore(ap->lock, flags);
+       cancel_rearming_delayed_work(&ap->port_task);
 
        if (ata_msg_ctl(ap))
                ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
@@ -1814,7 +1785,7 @@ static void ata_dev_config_ncq(struct ata_device *dev,
                desc[0] = '\0';
                return;
        }
-       if (ata_device_blacklisted(dev) & ATA_HORKAGE_NONCQ) {
+       if (dev->horkage & ATA_HORKAGE_NONCQ) {
                snprintf(desc, desc_sz, "NCQ (not used)");
                return;
        }
@@ -1863,6 +1834,9 @@ int ata_dev_configure(struct ata_device *dev)
        if (ata_msg_probe(ap))
                ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
 
+       /* set horkage */
+       dev->horkage |= ata_dev_blacklisted(dev);
+
        /* let ACPI work its magic */
        rc = ata_acpi_on_devcfg(dev);
        if (rc)
@@ -2038,7 +2012,7 @@ int ata_dev_configure(struct ata_device *dev)
                dev->max_sectors = ATA_MAX_SECTORS;
        }
 
-       if (ata_device_blacklisted(dev) & ATA_HORKAGE_MAX_SEC_128)
+       if (dev->horkage & ATA_HORKAGE_MAX_SEC_128)
                dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
                                         dev->max_sectors);
 
@@ -3190,9 +3164,6 @@ void ata_bus_reset(struct ata_port *ap)
        if ((slave_possible) && (err != 0x81))
                ap->device[1].class = ata_dev_try_classify(ap, 1, &err);
 
-       /* re-enable interrupts */
-       ap->ops->irq_on(ap);
-
        /* is double-select really necessary? */
        if (ap->device[1].class != ATA_DEV_NONE)
                ap->ops->dev_select(ap, 1);
@@ -3577,10 +3548,6 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
        if (sata_scr_read(ap, SCR_ERROR, &serror) == 0)
                sata_scr_write(ap, SCR_ERROR, serror);
 
-       /* re-enable interrupts */
-       if (!ap->ops->error_handler)
-               ap->ops->irq_on(ap);
-
        /* is double-select really necessary? */
        if (classes[0] != ATA_DEV_NONE)
                ap->ops->dev_select(ap, 1);
@@ -3770,6 +3737,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "SAMSUNG CD-ROM SN-124","N001",       ATA_HORKAGE_NODMA },
        { "Seagate STT20000A", NULL,            ATA_HORKAGE_NODMA },
        { "IOMEGA  ZIP 250       ATAPI", NULL,  ATA_HORKAGE_NODMA }, /* temporary fix */
+       { "IOMEGA  ZIP 250       ATAPI       Floppy",
+                               NULL,           ATA_HORKAGE_NODMA },
 
        /* Weird ATAPI devices */
        { "TORiSAN DVD-ROM DRD-N216", NULL,     ATA_HORKAGE_MAX_SEC_128 },
@@ -3783,7 +3752,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "FUJITSU MHT2060BH",  NULL,           ATA_HORKAGE_NONCQ },
        /* NCQ is broken */
        { "Maxtor 6L250S0",     "BANC1G10",     ATA_HORKAGE_NONCQ },
+       { "Maxtor 6B200M0",     "BANC1BM0",     ATA_HORKAGE_NONCQ },
        { "Maxtor 6B200M0",     "BANC1B10",     ATA_HORKAGE_NONCQ },
+       { "HITACHI HDS7250SASUN500G 0621KTAWSD", "K2AOAJ0AHITACHI",
+        ATA_HORKAGE_NONCQ },
        /* NCQ hard hangs device under heavier load, needs hard power cycle */
        { "Maxtor 6B250S0",     "BANC1B70",     ATA_HORKAGE_NONCQ },
        /* Blacklist entries taken from Silicon Image 3124/3132
@@ -3796,6 +3768,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "HTS541612J9SA00",    "SBDIC7JP",     ATA_HORKAGE_NONCQ, },
        { "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, },
        { "WDC WD740ADFD-00NLR1", NULL,         ATA_HORKAGE_NONCQ, },
+       { "FUJITSU MHV2080BH",  "00840028",     ATA_HORKAGE_NONCQ, },
 
        /* Devices with NCQ limits */
 
@@ -3803,7 +3776,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { }
 };
 
-unsigned long ata_device_blacklisted(const struct ata_device *dev)
+static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
 {
        unsigned char model_num[ATA_ID_PROD_LEN + 1];
        unsigned char model_rev[ATA_ID_FW_REV_LEN + 1];
@@ -3833,7 +3806,7 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
        if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
            (dev->flags & ATA_DFLAG_CDB_INTR))
                return 1;
-       return (ata_device_blacklisted(dev) & ATA_HORKAGE_NODMA) ? 1 : 0;
+       return (dev->horkage & ATA_HORKAGE_NODMA) ? 1 : 0;
 }
 
 /**
@@ -6557,13 +6530,7 @@ void ata_port_detach(struct ata_port *ap)
        spin_unlock_irqrestore(ap->lock, flags);
 
        ata_port_wait_eh(ap);
-
-       /* Flush hotplug task.  The sequence is similar to
-        * ata_port_flush_task().
-        */
-       cancel_work_sync(&ap->hotplug_task.work); /* akpm: why? */
-       cancel_delayed_work(&ap->hotplug_task);
-       cancel_work_sync(&ap->hotplug_task.work);
+       cancel_rearming_delayed_work(&ap->hotplug_task);
 
  skip_eh:
        /* remove the associated SCSI host */
@@ -6952,7 +6919,6 @@ EXPORT_SYMBOL_GPL(ata_host_resume);
 EXPORT_SYMBOL_GPL(ata_id_string);
 EXPORT_SYMBOL_GPL(ata_id_c_string);
 EXPORT_SYMBOL_GPL(ata_id_to_dma_mode);
-EXPORT_SYMBOL_GPL(ata_device_blacklisted);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
 EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
@@ -6961,9 +6927,9 @@ EXPORT_SYMBOL_GPL(ata_timing_merge);
 
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL_GPL(pci_test_config_bits);
-EXPORT_SYMBOL_GPL(ata_pci_init_native_host);
+EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
 EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
-EXPORT_SYMBOL_GPL(ata_pci_prepare_native_host);
+EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
 #ifdef CONFIG_PM
index 9ee0a8c08d96241c9b03109ca4cc67169e07e4c8..9aa62a0754f6946349a4c72d142f2f68eec0077e 100644 (file)
@@ -1897,6 +1897,57 @@ static int ata_eh_skip_recovery(struct ata_port *ap)
        return 1;
 }
 
+static void ata_eh_handle_dev_fail(struct ata_device *dev, int err)
+{
+       struct ata_port *ap = dev->ap;
+       struct ata_eh_context *ehc = &ap->eh_context;
+
+       ehc->tries[dev->devno]--;
+
+       switch (err) {
+       case -ENODEV:
+               /* device missing or wrong IDENTIFY data, schedule probing */
+               ehc->i.probe_mask |= (1 << dev->devno);
+       case -EINVAL:
+               /* give it just one more chance */
+               ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
+       case -EIO:
+               if (ehc->tries[dev->devno] == 1) {
+                       /* This is the last chance, better to slow
+                        * down than lose it.
+                        */
+                       sata_down_spd_limit(ap);
+                       ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
+               }
+       }
+
+       if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
+               /* disable device if it has used up all its chances */
+               ata_dev_disable(dev);
+
+               /* detach if offline */
+               if (ata_port_offline(ap))
+                       ata_eh_detach_dev(dev);
+
+               /* probe if requested */
+               if ((ehc->i.probe_mask & (1 << dev->devno)) &&
+                   !(ehc->did_probe_mask & (1 << dev->devno))) {
+                       ata_eh_detach_dev(dev);
+                       ata_dev_init(dev);
+
+                       ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+                       ehc->did_probe_mask |= (1 << dev->devno);
+                       ehc->i.action |= ATA_EH_SOFTRESET;
+               }
+       } else {
+               /* soft didn't work?  be haaaaard */
+               if (ehc->i.flags & ATA_EHI_DID_RESET)
+                       ehc->i.action |= ATA_EH_HARDRESET;
+               else
+                       ehc->i.action |= ATA_EH_SOFTRESET;
+       }
+}
+
 /**
  *     ata_eh_recover - recover host port after error
  *     @ap: host port to recover
@@ -1997,50 +2048,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
        goto out;
 
  dev_fail:
-       ehc->tries[dev->devno]--;
-
-       switch (rc) {
-       case -ENODEV:
-               /* device missing or wrong IDENTIFY data, schedule probing */
-               ehc->i.probe_mask |= (1 << dev->devno);
-       case -EINVAL:
-               /* give it just one more chance */
-               ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
-       case -EIO:
-               if (ehc->tries[dev->devno] == 1) {
-                       /* This is the last chance, better to slow
-                        * down than lose it.
-                        */
-                       sata_down_spd_limit(ap);
-                       ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
-               }
-       }
-
-       if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
-               /* disable device if it has used up all its chances */
-               ata_dev_disable(dev);
-
-               /* detach if offline */
-               if (ata_port_offline(ap))
-                       ata_eh_detach_dev(dev);
-
-               /* probe if requested */
-               if ((ehc->i.probe_mask & (1 << dev->devno)) &&
-                   !(ehc->did_probe_mask & (1 << dev->devno))) {
-                       ata_eh_detach_dev(dev);
-                       ata_dev_init(dev);
-
-                       ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
-                       ehc->did_probe_mask |= (1 << dev->devno);
-                       ehc->i.action |= ATA_EH_SOFTRESET;
-               }
-       } else {
-               /* soft didn't work?  be haaaaard */
-               if (ehc->i.flags & ATA_EHI_DID_RESET)
-                       ehc->i.action |= ATA_EH_HARDRESET;
-               else
-                       ehc->i.action |= ATA_EH_SOFTRESET;
-       }
+       ata_eh_handle_dev_fail(dev, rc);
 
        if (ata_port_nr_enabled(ap)) {
                ata_port_printk(ap, KERN_WARNING, "failed to recover some "
index fa1c22c7b38fef986e0029c139a471e53667459b..ca7d2245d6840b2580141ceae2b81542366a3d6e 100644 (file)
@@ -604,13 +604,17 @@ int ata_pci_init_bmdma(struct ata_host *host)
 }
 
 /**
- *     ata_pci_init_native_host - acquire native ATA resources and init host
+ *     ata_pci_init_sff_host - acquire native PCI ATA resources and init host
  *     @host: target ATA host
  *
  *     Acquire native PCI ATA resources for @host and initialize the
  *     first two ports of @host accordingly.  Ports marked dummy are
  *     skipped and allocation failure makes the port dummy.
  *
+ *     Note that native PCI resources are valid even for legacy hosts
+ *     as we fix up pdev resources array early in boot, so this
+ *     function can be used for both native and legacy SFF hosts.
+ *
  *     LOCKING:
  *     Inherited from calling layer (may sleep).
  *
@@ -618,7 +622,7 @@ int ata_pci_init_bmdma(struct ata_host *host)
  *     0 if at least one port is initialized, -ENODEV if no port is
  *     available.
  */
-int ata_pci_init_native_host(struct ata_host *host)
+int ata_pci_init_sff_host(struct ata_host *host)
 {
        struct device *gdev = host->dev;
        struct pci_dev *pdev = to_pci_dev(gdev);
@@ -673,7 +677,7 @@ int ata_pci_init_native_host(struct ata_host *host)
 }
 
 /**
- *     ata_pci_prepare_native_host - helper to prepare native PCI ATA host
+ *     ata_pci_prepare_sff_host - helper to prepare native PCI ATA host
  *     @pdev: target PCI device
  *     @ppi: array of port_info, must be enough for two ports
  *     @r_host: out argument for the initialized ATA host
@@ -687,9 +691,9 @@ int ata_pci_init_native_host(struct ata_host *host)
  *     RETURNS:
  *     0 on success, -errno otherwise.
  */
-int ata_pci_prepare_native_host(struct pci_dev *pdev,
-                               const struct ata_port_info * const * ppi,
-                               struct ata_host **r_host)
+int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+                            const struct ata_port_info * const * ppi,
+                            struct ata_host **r_host)
 {
        struct ata_host *host;
        int rc;
@@ -705,7 +709,7 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev,
                goto err_out;
        }
 
-       rc = ata_pci_init_native_host(host);
+       rc = ata_pci_init_sff_host(host);
        if (rc)
                goto err_out;
 
@@ -730,221 +734,6 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev,
        return rc;
 }
 
-struct ata_legacy_devres {
-       unsigned int    mask;
-       unsigned long   cmd_port[2];
-       void __iomem *  cmd_addr[2];
-       void __iomem *  ctl_addr[2];
-       unsigned int    irq[2];
-       void *          irq_dev_id[2];
-};
-
-static void ata_legacy_free_irqs(struct ata_legacy_devres *legacy_dr)
-{
-       int i;
-
-       for (i = 0; i < 2; i++) {
-               if (!legacy_dr->irq[i])
-                       continue;
-
-               free_irq(legacy_dr->irq[i], legacy_dr->irq_dev_id[i]);
-               legacy_dr->irq[i] = 0;
-               legacy_dr->irq_dev_id[i] = NULL;
-       }
-}
-
-static void ata_legacy_release(struct device *gdev, void *res)
-{
-       struct ata_legacy_devres *this = res;
-       int i;
-
-       ata_legacy_free_irqs(this);
-
-       for (i = 0; i < 2; i++) {
-               if (this->cmd_addr[i])
-                       ioport_unmap(this->cmd_addr[i]);
-               if (this->ctl_addr[i])
-                       ioport_unmap(this->ctl_addr[i]);
-               if (this->cmd_port[i])
-                       release_region(this->cmd_port[i], 8);
-       }
-}
-
-static int ata_init_legacy_port(struct ata_port *ap,
-                               struct ata_legacy_devres *legacy_dr)
-{
-       struct ata_host *host = ap->host;
-       int port_no = ap->port_no;
-       unsigned long cmd_port, ctl_port;
-
-       if (port_no == 0) {
-               cmd_port = ATA_PRIMARY_CMD;
-               ctl_port = ATA_PRIMARY_CTL;
-       } else {
-               cmd_port = ATA_SECONDARY_CMD;
-               ctl_port = ATA_SECONDARY_CTL;
-       }
-
-       /* request cmd_port */
-       if (request_region(cmd_port, 8, "libata"))
-               legacy_dr->cmd_port[port_no] = cmd_port;
-       else {
-               dev_printk(KERN_WARNING, host->dev,
-                          "0x%0lX IDE port busy\n", cmd_port);
-               return -EBUSY;
-       }
-
-       /* iomap cmd and ctl ports */
-       legacy_dr->cmd_addr[port_no] = ioport_map(cmd_port, 8);
-       legacy_dr->ctl_addr[port_no] = ioport_map(ctl_port, 1);
-       if (!legacy_dr->cmd_addr[port_no] || !legacy_dr->ctl_addr[port_no]) {
-               dev_printk(KERN_WARNING, host->dev,
-                          "failed to map cmd/ctl ports\n");
-               return -ENOMEM;
-       }
-
-       /* init IO addresses */
-       ap->ioaddr.cmd_addr = legacy_dr->cmd_addr[port_no];
-       ap->ioaddr.altstatus_addr = legacy_dr->ctl_addr[port_no];
-       ap->ioaddr.ctl_addr = legacy_dr->ctl_addr[port_no];
-       ata_std_ports(&ap->ioaddr);
-
-       return 0;
-}
-
-/**
- *     ata_init_legacy_host - acquire legacy ATA resources and init ATA host
- *     @host: target ATA host
- *     @was_busy: out parameter, indicates whether any port was busy
- *
- *     Acquire legacy ATA resources for the first two ports of @host
- *     and initialize it accordingly.  Ports marked dummy are skipped
- *     and resource acquistion failure makes the port dummy.
- *
- *     LOCKING:
- *     Inherited from calling layer (may sleep).
- *
- *     RETURNS:
- *     0 if at least one port is initialized, -ENODEV if no port is
- *     available.
- */
-static int ata_init_legacy_host(struct ata_host *host, int *was_busy)
-{
-       struct device *gdev = host->dev;
-       struct ata_legacy_devres *legacy_dr;
-       int i, rc;
-
-       if (!devres_open_group(gdev, NULL, GFP_KERNEL))
-               return -ENOMEM;
-
-       rc = -ENOMEM;
-       legacy_dr = devres_alloc(ata_legacy_release, sizeof(*legacy_dr),
-                                GFP_KERNEL);
-       if (!legacy_dr)
-               goto err_out;
-       devres_add(gdev, legacy_dr);
-
-       for (i = 0; i < 2; i++) {
-               if (ata_port_is_dummy(host->ports[i]))
-                       continue;
-
-               rc = ata_init_legacy_port(host->ports[i], legacy_dr);
-               if (rc == 0)
-                       legacy_dr->mask |= 1 << i;
-               else {
-                       if (rc == -EBUSY)
-                               (*was_busy)++;
-                       host->ports[i]->ops = &ata_dummy_port_ops;
-               }
-       }
-
-       if (!legacy_dr->mask) {
-               dev_printk(KERN_ERR, gdev, "no available legacy port\n");
-               return -ENODEV;
-       }
-
-       devres_remove_group(gdev, NULL);
-       return 0;
-
- err_out:
-       devres_release_group(gdev, NULL);
-       return rc;
-}
-
-/**
- *     ata_request_legacy_irqs - request legacy ATA IRQs
- *     @host: target ATA host
- *     @handler: array of IRQ handlers
- *     @irq_flags: array of IRQ flags
- *     @dev_id: array of IRQ dev_ids
- *
- *     Request legacy IRQs for non-dummy legacy ports in @host.  All
- *     IRQ parameters are passed as array to allow ports to have
- *     separate IRQ handlers.
- *
- *     LOCKING:
- *     Inherited from calling layer (may sleep).
- *
- *     RETURNS:
- *     0 on success, -errno otherwise.
- */
-static int ata_request_legacy_irqs(struct ata_host *host,
-                                  irq_handler_t const *handler,
-                                  const unsigned int *irq_flags,
-                                  void * const *dev_id)
-{
-       struct device *gdev = host->dev;
-       struct ata_legacy_devres *legacy_dr;
-       int i, rc;
-
-       legacy_dr = devres_find(host->dev, ata_legacy_release, NULL, NULL);
-       BUG_ON(!legacy_dr);
-
-       for (i = 0; i < 2; i++) {
-               unsigned int irq;
-
-               /* FIXME: ATA_*_IRQ() should take generic device not pci_dev */
-               if (i == 0)
-                       irq = ATA_PRIMARY_IRQ(to_pci_dev(gdev));
-               else
-                       irq = ATA_SECONDARY_IRQ(to_pci_dev(gdev));
-
-               if (!(legacy_dr->mask & (1 << i)))
-                       continue;
-
-               if (!handler[i]) {
-                       dev_printk(KERN_ERR, gdev,
-                                  "NULL handler specified for port %d\n", i);
-                       rc = -EINVAL;
-                       goto err_out;
-               }
-
-               rc = request_irq(irq, handler[i], irq_flags[i], DRV_NAME,
-                                dev_id[i]);
-               if (rc) {
-                       dev_printk(KERN_ERR, gdev,
-                               "irq %u request failed (errno=%d)\n", irq, rc);
-                       goto err_out;
-               }
-
-               /* record irq allocation in legacy_dr */
-               legacy_dr->irq[i] = irq;
-               legacy_dr->irq_dev_id[i] = dev_id[i];
-
-               /* only used to print info */
-               if (i == 0)
-                       host->irq = irq;
-               else
-                       host->irq2 = irq;
-       }
-
-       return 0;
-
- err_out:
-       ata_legacy_free_irqs(legacy_dr);
-       return rc;
-}
-
 /**
  *     ata_pci_init_one - Initialize/register PCI IDE host controller
  *     @pdev: Controller to be initialized
@@ -1029,35 +818,11 @@ int ata_pci_init_one(struct pci_dev *pdev,
 #endif
        }
 
-       /* alloc and init host */
-       host = ata_host_alloc_pinfo(dev, ppi, 2);
-       if (!host) {
-               dev_printk(KERN_ERR, &pdev->dev,
-                          "failed to allocate ATA host\n");
-               rc = -ENOMEM;
+       /* prepare host */
+       rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
+       if (rc)
                goto err_out;
-       }
 
-       if (!legacy_mode) {
-               rc = ata_pci_init_native_host(host);
-               if (rc)
-                       goto err_out;
-       } else {
-               int was_busy = 0;
-
-               rc = ata_init_legacy_host(host, &was_busy);
-               if (was_busy)
-                       pcim_pin_device(pdev);
-               if (rc)
-                       goto err_out;
-
-               /* request respective PCI regions, may fail */
-               rc = pci_request_region(pdev, 1, DRV_NAME);
-               rc = pci_request_region(pdev, 3, DRV_NAME);
-       }
-
-       /* init BMDMA, may fail */
-       ata_pci_init_bmdma(host);
        pci_set_master(pdev);
 
        /* start host and request IRQ */
@@ -1068,17 +833,28 @@ int ata_pci_init_one(struct pci_dev *pdev,
        if (!legacy_mode) {
                rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler,
                                      IRQF_SHARED, DRV_NAME, host);
+               if (rc)
+                       goto err_out;
                host->irq = pdev->irq;
        } else {
-               irq_handler_t handler[2] = { host->ops->irq_handler,
-                                            host->ops->irq_handler };
-               unsigned int irq_flags[2] = { IRQF_SHARED, IRQF_SHARED };
-               void *dev_id[2] = { host, host };
+               if (!ata_port_is_dummy(host->ports[0])) {
+                       host->irq = ATA_PRIMARY_IRQ(pdev);
+                       rc = devm_request_irq(dev, host->irq,
+                                             pi->port_ops->irq_handler,
+                                             IRQF_SHARED, DRV_NAME, host);
+                       if (rc)
+                               goto err_out;
+               }
 
-               rc = ata_request_legacy_irqs(host, handler, irq_flags, dev_id);
+               if (!ata_port_is_dummy(host->ports[1])) {
+                       host->irq2 = ATA_SECONDARY_IRQ(pdev);
+                       rc = devm_request_irq(dev, host->irq2,
+                                             pi->port_ops->irq_handler,
+                                             IRQF_SHARED, DRV_NAME, host);
+                       if (rc)
+                               goto err_out;
+               }
        }
-       if (rc)
-               goto err_out;
 
        /* register */
        rc = ata_host_register(host, pi->sht);
index 30c4276ec882fdf4c004910974ee63b3070efbe4..010436795d202768ab1da333f6484a28f4ea6d54 100644 (file)
@@ -455,23 +455,21 @@ static struct ata_port_operations ali_c5_port_ops = {
 
 static void ali_init_chipset(struct pci_dev *pdev)
 {
-       u8 rev, tmp;
+       u8 tmp;
        struct pci_dev *north, *isa_bridge;
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-
        /*
         * The chipset revision selects the driver operations and
         * mode data.
         */
 
-       if (rev >= 0x20 && rev < 0xC2) {
+       if (pdev->revision >= 0x20 && pdev->revision < 0xC2) {
                /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
                pci_read_config_byte(pdev, 0x4B, &tmp);
                /* Clear CD-ROM DMA write bit */
                tmp &= 0x7F;
                pci_write_config_byte(pdev, 0x4B, tmp);
-       } else if (rev >= 0xC2) {
+       } else if (pdev->revision >= 0xC2) {
                /* Enable cable detection logic */
                pci_read_config_byte(pdev, 0x4B, &tmp);
                pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
@@ -483,21 +481,21 @@ static void ali_init_chipset(struct pci_dev *pdev)
                /* Configure the ALi bridge logic. For non ALi rely on BIOS.
                   Set the south bridge enable bit */
                pci_read_config_byte(isa_bridge, 0x79, &tmp);
-               if (rev == 0xC2)
+               if (pdev->revision == 0xC2)
                        pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04);
-               else if (rev > 0xC2 && rev < 0xC5)
+               else if (pdev->revision > 0xC2 && pdev->revision < 0xC5)
                        pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02);
        }
-       if (rev >= 0x20) {
+       if (pdev->revision >= 0x20) {
                /*
                 * CD_ROM DMA on (0x53 bit 0). Enable this even if we want
                 * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
                 * via 0x54/55.
                 */
                pci_read_config_byte(pdev, 0x53, &tmp);
-               if (rev <= 0x20)
+               if (pdev->revision <= 0x20)
                        tmp &= ~0x02;
-               if (rev >= 0xc7)
+               if (pdev->revision >= 0xc7)
                        tmp |= 0x03;
                else
                        tmp |= 0x01;    /* CD_ROM enable for DMA */
@@ -579,25 +577,23 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        };
 
        const struct ata_port_info *ppi[] = { NULL, NULL };
-       u8 rev, tmp;
+       u8 tmp;
        struct pci_dev *isa_bridge;
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-
        /*
         * The chipset revision selects the driver operations and
         * mode data.
         */
 
-       if (rev < 0x20) {
+       if (pdev->revision < 0x20) {
                ppi[0] = &info_early;
-       } else if (rev < 0xC2) {
+       } else if (pdev->revision < 0xC2) {
                ppi[0] = &info_20;
-       } else if (rev == 0xC2) {
+       } else if (pdev->revision == 0xC2) {
                ppi[0] = &info_c2;
-       } else if (rev == 0xC3) {
+       } else if (pdev->revision == 0xC3) {
                ppi[0] = &info_c3;
-       } else if (rev == 0xC4) {
+       } else if (pdev->revision == 0xC4) {
                ppi[0] = &info_c4;
        } else
                ppi[0] = &info_c5;
@@ -605,7 +601,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        ali_init_chipset(pdev);
 
        isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
-       if (isa_bridge && rev >= 0x20 && rev < 0xC2) {
+       if (isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
                /* Are we paired with a UDMA capable chip */
                pci_read_config_byte(isa_bridge, 0x5E, &tmp);
                if ((tmp & 0x1E) == 0x12)
index b9c44c575ce3f42c5bddf10cf994e788a7432b13..b09facad63e17a0f4dac7e64f854b39592899cb0 100644 (file)
@@ -623,17 +623,15 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        const struct ata_port_info *ppi[] = { NULL, NULL };
        static int printed_version;
        int type = id->driver_data;
-       u8 rev;
        u8 fifo;
 
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
        pci_read_config_byte(pdev, 0x41, &fifo);
 
        /* Check for AMD7409 without swdma errata and if found adjust type */
-       if (type == 1 && rev > 0x7)
+       if (type == 1 && pdev->revision > 0x7)
                type = 2;
 
        /* Check for AMD7411 */
index 3fca5898642b62f05bb0fc0f472d6a732cb603bb..68f150a1e2f480b42d42ca88895563ba6a91fa16 100644 (file)
@@ -266,7 +266,7 @@ static int cs5530_init_chip(void)
        }
 
        pci_set_master(cs5530_0);
-       pci_set_mwi(cs5530_0);
+       pci_try_set_mwi(cs5530_0);
 
        /*
         * Set PCI CacheLineSize to 16-bytes:
index d928c91050345c6834baa7d4990f77673ed972b2..be0f05efac6d1c93a87628b37d1a3d62afc9ad4e 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_hpt3x3"
-#define DRV_VERSION    "0.4.3"
+#define DRV_VERSION    "0.5.3"
 
 /**
  *     hpt3x3_set_piomode              -       PIO setup
@@ -52,6 +52,7 @@ static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev)
        pci_write_config_dword(pdev, 0x48, r2);
 }
 
+#if defined(CONFIG_PATA_HPT3X3_DMA)
 /**
  *     hpt3x3_set_dmamode              -       DMA timing setup
  *     @ap: ATA interface
@@ -59,6 +60,9 @@ static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev)
  *
  *     Set up the channel for MWDMA or UDMA modes. Much the same as with
  *     PIO, load the mode number and then set MWDMA or UDMA flag.
+ *
+ *     0x44 : bit 0-2 master mode, 3-5 slave mode, etc
+ *     0x48 : bit 4/0 DMA/UDMA bit 5/1 for slave etc
  */
 
 static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev)
@@ -76,13 +80,26 @@ static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev)
        r2 &= ~(0x11 << dn);    /* Clear MWDMA and UDMA bits */
 
        if (adev->dma_mode >= XFER_UDMA_0)
-               r2 |= 0x01 << dn;       /* Ultra mode */
+               r2 |= (0x10 << dn);     /* Ultra mode */
        else
-               r2 |= 0x10 << dn;       /* MWDMA */
+               r2 |= (0x01 << dn);     /* MWDMA */
 
        pci_write_config_dword(pdev, 0x44, r1);
        pci_write_config_dword(pdev, 0x48, r2);
 }
+#endif /* CONFIG_PATA_HPT3X3_DMA */
+
+/**
+ *     hpt3x3_atapi_dma        -       ATAPI DMA check
+ *     @qc: Queued command
+ *
+ *     Just say no - we don't do ATAPI DMA
+ */
+
+static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc)
+{
+       return 1;
+}
 
 static struct scsi_host_template hpt3x3_sht = {
        .module                 = THIS_MODULE,
@@ -105,7 +122,9 @@ static struct scsi_host_template hpt3x3_sht = {
 static struct ata_port_operations hpt3x3_port_ops = {
        .port_disable   = ata_port_disable,
        .set_piomode    = hpt3x3_set_piomode,
+#if defined(CONFIG_PATA_HPT3X3_DMA)
        .set_dmamode    = hpt3x3_set_dmamode,
+#endif
        .mode_filter    = ata_pci_default_filter,
 
        .tf_load        = ata_tf_load,
@@ -124,6 +143,7 @@ static struct ata_port_operations hpt3x3_port_ops = {
        .bmdma_start    = ata_bmdma_start,
        .bmdma_stop     = ata_bmdma_stop,
        .bmdma_status   = ata_bmdma_status,
+       .check_atapi_dma= hpt3x3_atapi_dma,
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
@@ -158,32 +178,79 @@ static void hpt3x3_init_chipset(struct pci_dev *dev)
                pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
 }
 
-
 /**
  *     hpt3x3_init_one         -       Initialise an HPT343/363
- *     @dev: PCI device
+ *     @pdev: PCI device
  *     @id: Entry in match table
  *
- *     Perform basic initialisation. The chip has a quirk that it won't
- *     function unless it is at XX00. The old ATA driver touched this up
- *     but we leave it for pci quirks to do properly.
+ *     Perform basic initialisation. We set the device up so we access all
+ *     ports via BAR4. This is neccessary to work around errata.
  */
 
-static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
+       static int printed_version;
        static const struct ata_port_info info = {
                .sht = &hpt3x3_sht,
                .flags = ATA_FLAG_SLAVE_POSS,
                .pio_mask = 0x1f,
+#if defined(CONFIG_PATA_HPT3X3_DMA)
+               /* Further debug needed */
                .mwdma_mask = 0x07,
                .udma_mask = 0x07,
+#endif
                .port_ops = &hpt3x3_port_ops
        };
+       /* Register offsets of taskfiles in BAR4 area */
+       static const u8 offset_cmd[2] = { 0x20, 0x28 };
+       static const u8 offset_ctl[2] = { 0x36, 0x3E };
        const struct ata_port_info *ppi[] = { &info, NULL };
-
-       hpt3x3_init_chipset(dev);
-       /* Now kick off ATA set up */
-       return ata_pci_init_one(dev, ppi);
+       struct ata_host *host;
+       int i, rc;
+       void __iomem *base;
+
+       hpt3x3_init_chipset(pdev);
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
+       if (!host)
+               return -ENOMEM;
+       /* acquire resources and fill host */
+       rc = pcim_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       /* Everything is relative to BAR4 if we set up this way */
+       rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME);
+       if (rc == -EBUSY)
+               pcim_pin_device(pdev);
+       if (rc)
+               return rc;
+       host->iomap = pcim_iomap_table(pdev);
+       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       if (rc)
+               return rc;
+       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       if (rc)
+               return rc;
+
+       base = host->iomap[4];  /* Bus mastering base */
+
+       for (i = 0; i < host->n_ports; i++) {
+               struct ata_ioports *ioaddr = &host->ports[i]->ioaddr;
+
+               ioaddr->cmd_addr = base + offset_cmd[i];
+               ioaddr->altstatus_addr =
+               ioaddr->ctl_addr = base + offset_ctl[i];
+               ioaddr->scr_addr = NULL;
+               ata_std_ports(ioaddr);
+               ioaddr->bmdma_addr = base + 8 * i;
+       }
+       pci_set_master(pdev);
+       return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+                                &hpt3x3_sht);
 }
 
 #ifdef CONFIG_PM
index b67bbf6516ba2869a3883c8a2c002591d98ff0b6..430673be1df7560aea3d4be5c9f85e1c53fb0ceb 100644 (file)
@@ -587,8 +587,7 @@ static int it821x_port_start(struct ata_port *ap)
        itdev->want[1][1] = ATA_ANY;
        itdev->last_device = -1;
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &conf);
-       if (conf == 0x10) {
+       if (pdev->revision == 0x11) {
                itdev->timing10 = 1;
                /* Need to disable ATAPI DMA for this case */
                if (!itdev->smart)
index 368fac7d168be3cbb79a4ea1c6fa032360b1804c..182e83c9047b2bed550b82194c2daabd522437be 100644 (file)
@@ -467,13 +467,27 @@ mpc52xx_ata_remove(struct of_device *op)
 static int
 mpc52xx_ata_suspend(struct of_device *op, pm_message_t state)
 {
-       return 0;       /* FIXME : What to do here ? */
+       struct ata_host *host = dev_get_drvdata(&op->dev);
+
+       return ata_host_suspend(host, state);
 }
 
 static int
 mpc52xx_ata_resume(struct of_device *op)
 {
-       return 0;       /* FIXME : What to do here ? */
+       struct ata_host *host = dev_get_drvdata(&op->dev);
+       struct mpc52xx_ata_priv *priv = host->private_data;
+       int rv;
+
+       rv = mpc52xx_ata_hw_init(priv);
+       if (rv) {
+               printk(KERN_ERR DRV_NAME ": Error during HW init\n");
+               return rv;
+       }
+
+       ata_host_resume(host);
+
+       return 0;
 }
 
 #endif
index 61502bc7bf1d4bcf06a74fc2452371eb0da21aa8..c55667e0eb65a5978f2b786707afad88f5c30e6e 100644 (file)
@@ -238,6 +238,12 @@ static void scc_set_dmamode (struct ata_port *ap, struct ata_device *adev)
        else
                offset = 0;     /* 100MHz */
 
+       /* errata A308 workaround: limit ATAPI UDMA mode to UDMA4 */
+       if (adev->class == ATA_DEV_ATAPI && speed > XFER_UDMA_4) {
+               printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME);
+               speed = XFER_UDMA_4;
+       }
+
        if (speed >= XFER_UDMA_0)
                idx = speed - XFER_UDMA_0;
        else
@@ -724,22 +730,36 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc)
 
 static u8 scc_bmdma_status (struct ata_port *ap)
 {
-       u8 host_stat;
        void __iomem *mmio = ap->ioaddr.bmdma_addr;
-
-       host_stat = in_be32(mmio + SCC_DMA_STATUS);
-
-       /* Workaround for PTERADD: emulate DMA_INTR when
-        * - IDE_STATUS[ERR] = 1
-        * - INT_STATUS[INTRQ] = 1
-        * - DMA_STATUS[IORACTA] = 1
-        */
-       if (!(host_stat & ATA_DMA_INTR)) {
-               u32 int_status = in_be32(mmio + SCC_DMA_INTST);
-               if (ata_altstatus(ap) & ATA_ERR &&
-                   int_status & INTSTS_INTRQ &&
-                   host_stat & ATA_DMA_ACTIVE)
-                       host_stat |= ATA_DMA_INTR;
+       u8 host_stat = in_be32(mmio + SCC_DMA_STATUS);
+       u32 int_status = in_be32(mmio + SCC_DMA_INTST);
+       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+       static int retry = 0;
+
+       /* return if IOS_SS is cleared */
+       if (!(in_be32(mmio + SCC_DMA_CMD) & ATA_DMA_START))
+               return host_stat;
+
+       /* errata A252,A308 workaround: Step4 */
+       if (ata_altstatus(ap) & ATA_ERR && int_status & INTSTS_INTRQ)
+               return (host_stat | ATA_DMA_INTR);
+
+       /* errata A308 workaround Step5 */
+       if (int_status & INTSTS_IOIRQS) {
+               host_stat |= ATA_DMA_INTR;
+
+               /* We don't check ATAPI DMA because it is limited to UDMA4 */
+               if ((qc->tf.protocol == ATA_PROT_DMA &&
+                    qc->dev->xfer_mode > XFER_UDMA_4)) {
+                       if (!(int_status & INTSTS_ACTEINT)) {
+                               printk(KERN_WARNING "ata%u: data lost occurred. (ACTEINT==0, retry:%d)\n",
+                                      ap->print_id, retry);
+                               host_stat |= ATA_DMA_ERR;
+                               if (retry++)
+                                       ap->udma_mask >>= 1;
+                       } else
+                               retry = 0;
+               }
        }
 
        return host_stat;
@@ -892,10 +912,6 @@ static void scc_std_postreset (struct ata_port *ap, unsigned int *classes)
 {
        DPRINTK("ENTER\n");
 
-       /* re-enable interrupts */
-       if (!ap->ops->error_handler)
-               ap->ops->irq_on(ap);
-
        /* is double-select really necessary? */
        if (classes[0] != ATA_DEV_NONE)
                ap->ops->dev_select(ap, 1);
index 0231aba51ca46819017d9a0017a79d50fa936b82..89691541fe5936f9e2c51a8c27dc2b6b0dffafb9 100644 (file)
@@ -410,11 +410,8 @@ static int serverworks_fixup_osb4(struct pci_dev *pdev)
 
 static int serverworks_fixup_csb(struct pci_dev *pdev)
 {
-       u8 rev;
        u8 btr;
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-
        /* Third Channel Test */
        if (!(PCI_FUNC(pdev->devfn) & 1)) {
                struct pci_dev * findev = NULL;
@@ -456,7 +453,7 @@ static int serverworks_fixup_csb(struct pci_dev *pdev)
        if (!(PCI_FUNC(pdev->devfn) & 1))
                btr |= 0x2;
        else
-               btr |= (rev >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
+               btr |= (pdev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
        pci_write_config_byte(pdev, 0x5A, btr);
 
        return btr;
index 2b4508206a6cd3753344405ff5c131e9a75abbea..9a829a7cbc60c11b14606327c2cb940868a675fc 100644 (file)
@@ -149,6 +149,9 @@ static int sis_pre_reset(struct ata_port *ap, unsigned long deadline)
        if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no]))
                return -ENOENT;
 
+       /* Clear the FIFO settings. We can't enable the FIFO until
+          we know we are poking at a disk */
+       pci_write_config_byte(pdev, 0x4B, 0);
        return ata_std_prereset(ap, deadline);
 }
 
@@ -928,9 +931,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                if (host != NULL) {
                        chipset = sets;                 /* Match found */
                        if (sets->device == 0x630) {    /* SIS630 */
-                               u8 host_rev;
-                               pci_read_config_byte(host, PCI_REVISION_ID, &host_rev);
-                               if (host_rev >= 0x30)   /* 630 ET */
+                               if (host->revision >= 0x30)     /* 630 ET */
                                        chipset = &sis100_early;
                        }
                        break;
@@ -974,7 +975,6 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                u16 trueid;
                u8 prefctl;
                u8 idecfg;
-               u8 sbrev;
 
                /* Try the second unmasking technique */
                pci_read_config_byte(pdev, 0x4a, &idecfg);
@@ -987,11 +987,10 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                        lpc_bridge = pci_get_slot(pdev->bus, 0x10); /* Bus 0 Dev 2 Fn 0 */
                        if (lpc_bridge == NULL)
                                break;
-                       pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev);
                        pci_read_config_byte(pdev, 0x49, &prefctl);
                        pci_dev_put(lpc_bridge);
 
-                       if (sbrev == 0x10 && (prefctl & 0x80)) {
+                       if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
                                chipset = &sis133_early;
                                break;
                        }
index bde734189623af3b6ff033d546104bb9bfbbef12..8c2813aa6cdb39b6c52cdfe0a15e70364991b985 100644 (file)
@@ -270,7 +270,6 @@ static struct ata_port_operations sl82c105_port_ops = {
 static int sl82c105_bridge_revision(struct pci_dev *pdev)
 {
        struct pci_dev *bridge;
-       u8 rev;
 
        /*
         * The bridge should be part of the same device, but function 0.
@@ -292,10 +291,8 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
        /*
         * We need to find function 0's revision, not function 1
         */
-       pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
-
        pci_dev_put(bridge);
-       return rev;
+       return bridge->revision;
 }
 
 
index f0cadbe6aa1154b05f7cd0172f06395d5ff1f2ab..f645fe22cd1e7c6fb47df6591f7be1a12fc54114 100644 (file)
@@ -506,7 +506,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        struct pci_dev *isa = NULL;
        const struct via_isa_bridge *config;
        static int printed_version;
-       u8 t;
        u8 enable;
        u32 timing;
 
@@ -520,9 +519,8 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
                        !!(config->flags & VIA_BAD_ID),
                        config->id, NULL))) {
 
-                       pci_read_config_byte(isa, PCI_REVISION_ID, &t);
-                       if (t >= config->rev_min &&
-                           t <= config->rev_max)
+                       if (isa->revision >= config->rev_min &&
+                           isa->revision <= config->rev_max)
                                break;
                        pci_dev_put(isa);
                }
index 3873b29c80d6ec6bdb1328b0920ced97b0ee6ee0..5d576435fcccddd5fe0498c57c90c058e436de65 100644 (file)
   I distinctly remember a couple workarounds (one related to PCI-X)
   are still needed.
 
-  2) Convert to LibATA new EH.  Required for hotplug, NCQ, and sane
-  probing/error handling in general.  MUST HAVE.
-
-  3) Add hotplug support (easy, once new-EH support appears)
-
   4) Add NCQ support (easy to intermediate, once new-EH support appears)
 
   5) Investigate problems with PCI Message Signalled Interrupts (MSI).
@@ -108,8 +103,6 @@ enum {
        MV_SATAHC_ARBTR_REG_SZ  = MV_MINOR_REG_AREA_SZ,         /* arbiter */
        MV_PORT_REG_SZ          = MV_MINOR_REG_AREA_SZ,
 
-       MV_USE_Q_DEPTH          = ATA_DEF_QUEUE,
-
        MV_MAX_Q_DEPTH          = 32,
        MV_MAX_Q_DEPTH_MASK     = MV_MAX_Q_DEPTH - 1,
 
@@ -133,18 +126,22 @@ enum {
        /* Host Flags */
        MV_FLAG_DUAL_HC         = (1 << 30),  /* two SATA Host Controllers */
        MV_FLAG_IRQ_COALESCE    = (1 << 29),  /* IRQ coalescing capability */
-       MV_COMMON_FLAGS         = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
-                                  ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING),
+       MV_COMMON_FLAGS         = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
+                                 ATA_FLAG_PIO_POLLING,
        MV_6XXX_FLAGS           = MV_FLAG_IRQ_COALESCE,
 
        CRQB_FLAG_READ          = (1 << 0),
        CRQB_TAG_SHIFT          = 1,
+       CRQB_IOID_SHIFT         = 6,    /* CRQB Gen-II/IIE IO Id shift */
+       CRQB_HOSTQ_SHIFT        = 17,   /* CRQB Gen-II/IIE HostQueTag shift */
        CRQB_CMD_ADDR_SHIFT     = 8,
        CRQB_CMD_CS             = (0x2 << 11),
        CRQB_CMD_LAST           = (1 << 15),
 
        CRPB_FLAG_STATUS_SHIFT  = 8,
+       CRPB_IOID_SHIFT_6       = 5,    /* CRPB Gen-II IO Id shift */
+       CRPB_IOID_SHIFT_7       = 7,    /* CRPB Gen-IIE IO Id shift */
 
        EPRD_FLAG_END_OF_TBL    = (1 << 31),
 
@@ -236,8 +233,10 @@ enum {
        EDMA_ERR_DEV_DCON       = (1 << 3),
        EDMA_ERR_DEV_CON        = (1 << 4),
        EDMA_ERR_SERR           = (1 << 5),
-       EDMA_ERR_SELF_DIS       = (1 << 7),
+       EDMA_ERR_SELF_DIS       = (1 << 7),     /* Gen II/IIE self-disable */
+       EDMA_ERR_SELF_DIS_5     = (1 << 8),     /* Gen I self-disable */
        EDMA_ERR_BIST_ASYNC     = (1 << 8),
+       EDMA_ERR_TRANS_IRQ_7    = (1 << 8),     /* Gen IIE transprt layer irq */
        EDMA_ERR_CRBQ_PAR       = (1 << 9),
        EDMA_ERR_CRPB_PAR       = (1 << 10),
        EDMA_ERR_INTRL_PAR      = (1 << 11),
@@ -248,13 +247,33 @@ enum {
        EDMA_ERR_LNK_CTRL_TX    = (0x1f << 21),
        EDMA_ERR_LNK_DATA_TX    = (0x1f << 26),
        EDMA_ERR_TRANS_PROTO    = (1 << 31),
-       EDMA_ERR_FATAL          = (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
-                                  EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR |
-                                  EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR |
-                                  EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 |
-                                  EDMA_ERR_LNK_DATA_RX |
-                                  EDMA_ERR_LNK_DATA_TX |
-                                  EDMA_ERR_TRANS_PROTO),
+       EDMA_ERR_OVERRUN_5      = (1 << 5),
+       EDMA_ERR_UNDERRUN_5     = (1 << 6),
+       EDMA_EH_FREEZE          = EDMA_ERR_D_PAR |
+                                 EDMA_ERR_PRD_PAR |
+                                 EDMA_ERR_DEV_DCON |
+                                 EDMA_ERR_DEV_CON |
+                                 EDMA_ERR_SERR |
+                                 EDMA_ERR_SELF_DIS |
+                                 EDMA_ERR_CRBQ_PAR |
+                                 EDMA_ERR_CRPB_PAR |
+                                 EDMA_ERR_INTRL_PAR |
+                                 EDMA_ERR_IORDY |
+                                 EDMA_ERR_LNK_CTRL_RX_2 |
+                                 EDMA_ERR_LNK_DATA_RX |
+                                 EDMA_ERR_LNK_DATA_TX |
+                                 EDMA_ERR_TRANS_PROTO,
+       EDMA_EH_FREEZE_5        = EDMA_ERR_D_PAR |
+                                 EDMA_ERR_PRD_PAR |
+                                 EDMA_ERR_DEV_DCON |
+                                 EDMA_ERR_DEV_CON |
+                                 EDMA_ERR_OVERRUN_5 |
+                                 EDMA_ERR_UNDERRUN_5 |
+                                 EDMA_ERR_SELF_DIS_5 |
+                                 EDMA_ERR_CRBQ_PAR |
+                                 EDMA_ERR_CRPB_PAR |
+                                 EDMA_ERR_INTRL_PAR |
+                                 EDMA_ERR_IORDY,
 
        EDMA_REQ_Q_BASE_HI_OFS  = 0x10,
        EDMA_REQ_Q_IN_PTR_OFS   = 0x14,         /* also contains BASE_LO */
@@ -282,18 +301,18 @@ enum {
        MV_HP_ERRATA_60X1B2     = (1 << 3),
        MV_HP_ERRATA_60X1C0     = (1 << 4),
        MV_HP_ERRATA_XX42A0     = (1 << 5),
-       MV_HP_50XX              = (1 << 6),
-       MV_HP_GEN_IIE           = (1 << 7),
+       MV_HP_GEN_I             = (1 << 6),
+       MV_HP_GEN_II            = (1 << 7),
+       MV_HP_GEN_IIE           = (1 << 8),
 
        /* Port private flags (pp_flags) */
        MV_PP_FLAG_EDMA_EN      = (1 << 0),
        MV_PP_FLAG_EDMA_DS_ACT  = (1 << 1),
+       MV_PP_FLAG_HAD_A_RESET  = (1 << 2),
 };
 
-#define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX)
-#define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0)
-#define IS_GEN_I(hpriv) IS_50XX(hpriv)
-#define IS_GEN_II(hpriv) IS_60XX(hpriv)
+#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
+#define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
 #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
 
 enum {
@@ -352,6 +371,10 @@ struct mv_port_priv {
        dma_addr_t              crpb_dma;
        struct mv_sg            *sg_tbl;
        dma_addr_t              sg_tbl_dma;
+
+       unsigned int            req_idx;
+       unsigned int            resp_idx;
+
        u32                     pp_flags;
 };
 
@@ -384,14 +407,15 @@ static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
 static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
 static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
 static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
-static void mv_phy_reset(struct ata_port *ap);
-static void __mv_phy_reset(struct ata_port *ap, int can_sleep);
 static int mv_port_start(struct ata_port *ap);
 static void mv_port_stop(struct ata_port *ap);
 static void mv_qc_prep(struct ata_queued_cmd *qc);
 static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
 static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
-static void mv_eng_timeout(struct ata_port *ap);
+static void mv_error_handler(struct ata_port *ap);
+static void mv_post_int_cmd(struct ata_queued_cmd *qc);
+static void mv_eh_freeze(struct ata_port *ap);
+static void mv_eh_thaw(struct ata_port *ap);
 static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 
 static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
@@ -415,14 +439,31 @@ static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
 static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
 static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
                             unsigned int port_no);
-static void mv_stop_and_reset(struct ata_port *ap);
 
-static struct scsi_host_template mv_sht = {
+static struct scsi_host_template mv5_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = MV_MAX_SG_CT,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = 1,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = MV_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+static struct scsi_host_template mv6_sht = {
        .module                 = THIS_MODULE,
        .name                   = DRV_NAME,
        .ioctl                  = ata_scsi_ioctl,
        .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = MV_USE_Q_DEPTH,
+       .can_queue              = ATA_DEF_QUEUE,
        .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = MV_MAX_SG_CT,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
@@ -444,19 +485,21 @@ static const struct ata_port_operations mv5_ops = {
        .exec_command           = ata_exec_command,
        .dev_select             = ata_std_dev_select,
 
-       .phy_reset              = mv_phy_reset,
        .cable_detect           = ata_cable_sata,
 
        .qc_prep                = mv_qc_prep,
        .qc_issue               = mv_qc_issue,
        .data_xfer              = ata_data_xfer,
 
-       .eng_timeout            = mv_eng_timeout,
-
        .irq_clear              = mv_irq_clear,
        .irq_on                 = ata_irq_on,
        .irq_ack                = ata_irq_ack,
 
+       .error_handler          = mv_error_handler,
+       .post_internal_cmd      = mv_post_int_cmd,
+       .freeze                 = mv_eh_freeze,
+       .thaw                   = mv_eh_thaw,
+
        .scr_read               = mv5_scr_read,
        .scr_write              = mv5_scr_write,
 
@@ -473,19 +516,21 @@ static const struct ata_port_operations mv6_ops = {
        .exec_command           = ata_exec_command,
        .dev_select             = ata_std_dev_select,
 
-       .phy_reset              = mv_phy_reset,
        .cable_detect           = ata_cable_sata,
 
        .qc_prep                = mv_qc_prep,
        .qc_issue               = mv_qc_issue,
        .data_xfer              = ata_data_xfer,
 
-       .eng_timeout            = mv_eng_timeout,
-
        .irq_clear              = mv_irq_clear,
        .irq_on                 = ata_irq_on,
        .irq_ack                = ata_irq_ack,
 
+       .error_handler          = mv_error_handler,
+       .post_internal_cmd      = mv_post_int_cmd,
+       .freeze                 = mv_eh_freeze,
+       .thaw                   = mv_eh_thaw,
+
        .scr_read               = mv_scr_read,
        .scr_write              = mv_scr_write,
 
@@ -502,19 +547,21 @@ static const struct ata_port_operations mv_iie_ops = {
        .exec_command           = ata_exec_command,
        .dev_select             = ata_std_dev_select,
 
-       .phy_reset              = mv_phy_reset,
        .cable_detect           = ata_cable_sata,
 
        .qc_prep                = mv_qc_prep_iie,
        .qc_issue               = mv_qc_issue,
        .data_xfer              = ata_data_xfer,
 
-       .eng_timeout            = mv_eng_timeout,
-
        .irq_clear              = mv_irq_clear,
        .irq_on                 = ata_irq_on,
        .irq_ack                = ata_irq_ack,
 
+       .error_handler          = mv_error_handler,
+       .post_internal_cmd      = mv_post_int_cmd,
+       .freeze                 = mv_eh_freeze,
+       .thaw                   = mv_eh_thaw,
+
        .scr_read               = mv_scr_read,
        .scr_write              = mv_scr_write,
 
@@ -530,38 +577,38 @@ static const struct ata_port_info mv_port_info[] = {
                .port_ops       = &mv5_ops,
        },
        {  /* chip_508x */
-               .flags          = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+               .flags          = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
                .pio_mask       = 0x1f, /* pio0-4 */
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &mv5_ops,
        },
        {  /* chip_5080 */
-               .flags          = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+               .flags          = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
                .pio_mask       = 0x1f, /* pio0-4 */
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &mv5_ops,
        },
        {  /* chip_604x */
-               .flags          = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+               .flags          = MV_COMMON_FLAGS | MV_6XXX_FLAGS,
                .pio_mask       = 0x1f, /* pio0-4 */
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &mv6_ops,
        },
        {  /* chip_608x */
-               .flags          = (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
-                                  MV_FLAG_DUAL_HC),
+               .flags          = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
+                                 MV_FLAG_DUAL_HC,
                .pio_mask       = 0x1f, /* pio0-4 */
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &mv6_ops,
        },
        {  /* chip_6042 */
-               .flags          = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+               .flags          = MV_COMMON_FLAGS | MV_6XXX_FLAGS,
                .pio_mask       = 0x1f, /* pio0-4 */
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &mv_iie_ops,
        },
        {  /* chip_7042 */
-               .flags          = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+               .flags          = MV_COMMON_FLAGS | MV_6XXX_FLAGS,
                .pio_mask       = 0x1f, /* pio0-4 */
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &mv_iie_ops,
@@ -709,6 +756,46 @@ static void mv_irq_clear(struct ata_port *ap)
 {
 }
 
+static void mv_set_edma_ptrs(void __iomem *port_mmio,
+                            struct mv_host_priv *hpriv,
+                            struct mv_port_priv *pp)
+{
+       u32 index;
+
+       /*
+        * initialize request queue
+        */
+       index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
+
+       WARN_ON(pp->crqb_dma & 0x3ff);
+       writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
+       writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
+                port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+       if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
+               writelfl((pp->crqb_dma & 0xffffffff) | index,
+                        port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+       else
+               writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+
+       /*
+        * initialize response queue
+        */
+       index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
+
+       WARN_ON(pp->crpb_dma & 0xff);
+       writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
+
+       if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
+               writelfl((pp->crpb_dma & 0xffffffff) | index,
+                        port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+       else
+               writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+
+       writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
+                port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+}
+
 /**
  *      mv_start_dma - Enable eDMA engine
  *      @base: port base address
@@ -720,9 +807,15 @@ static void mv_irq_clear(struct ata_port *ap)
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
+static void mv_start_dma(void __iomem *base, struct mv_host_priv *hpriv,
+                        struct mv_port_priv *pp)
 {
-       if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
+       if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
+               /* clear EDMA event indicators, if any */
+               writelfl(0, base + EDMA_ERR_IRQ_CAUSE_OFS);
+
+               mv_set_edma_ptrs(base, hpriv, pp);
+
                writelfl(EDMA_EN, base + EDMA_CMD_OFS);
                pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
        }
@@ -739,14 +832,14 @@ static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_stop_dma(struct ata_port *ap)
+static int mv_stop_dma(struct ata_port *ap)
 {
        void __iomem *port_mmio = mv_ap_base(ap);
        struct mv_port_priv *pp = ap->private_data;
        u32 reg;
-       int i;
+       int i, err = 0;
 
-       if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) {
+       if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
                /* Disable EDMA if active.   The disable bit auto clears.
                 */
                writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
@@ -758,16 +851,18 @@ static void mv_stop_dma(struct ata_port *ap)
        /* now properly wait for the eDMA to stop */
        for (i = 1000; i > 0; i--) {
                reg = readl(port_mmio + EDMA_CMD_OFS);
-               if (!(EDMA_EN & reg)) {
+               if (!(reg & EDMA_EN))
                        break;
-               }
+
                udelay(100);
        }
 
-       if (EDMA_EN & reg) {
+       if (reg & EDMA_EN) {
                ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
-               /* FIXME: Consider doing a reset here to recover */
+               err = -EIO;
        }
+
+       return err;
 }
 
 #ifdef ATA_DEBUG
@@ -884,12 +979,13 @@ static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
                writelfl(val, mv_ap_base(ap) + ofs);
 }
 
-static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
+static void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
+                       void __iomem *port_mmio)
 {
        u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
 
        /* set up non-NCQ EDMA configuration */
-       cfg &= ~(1 << 9);       /* disable equeue */
+       cfg &= ~(1 << 9);       /* disable eQue */
 
        if (IS_GEN_I(hpriv)) {
                cfg &= ~0x1f;           /* clear queue depth */
@@ -909,7 +1005,7 @@ static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
                cfg |= (1 << 18);       /* enab early completion */
                cfg |= (1 << 17);       /* enab cut-through (dis stor&forwrd) */
                cfg &= ~(1 << 16);      /* dis FIS-based switching (for now) */
-               cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
+               cfg &= ~(EDMA_CFG_NCQ); /* clear NCQ */
        }
 
        writelfl(cfg, port_mmio + EDMA_CFG_OFS);
@@ -971,28 +1067,9 @@ static int mv_port_start(struct ata_port *ap)
        pp->sg_tbl = mem;
        pp->sg_tbl_dma = mem_dma;
 
-       mv_edma_cfg(hpriv, port_mmio);
+       mv_edma_cfg(ap, hpriv, port_mmio);
 
-       writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
-       writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK,
-                port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
-
-       if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
-               writelfl(pp->crqb_dma & 0xffffffff,
-                        port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
-       else
-               writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
-
-       writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
-
-       if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
-               writelfl(pp->crpb_dma & 0xffffffff,
-                        port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
-       else
-               writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
-
-       writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
-                port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+       mv_set_edma_ptrs(port_mmio, hpriv, pp);
 
        /* Don't turn on EDMA here...do it before DMA commands only.  Else
         * we'll be unable to send non-data, PIO, etc due to restricted access
@@ -1055,11 +1132,6 @@ static unsigned int mv_fill_sg(struct ata_queued_cmd *qc)
        return n_sg;
 }
 
-static inline unsigned mv_inc_q_index(unsigned index)
-{
-       return (index + 1) & MV_MAX_Q_DEPTH_MASK;
-}
-
 static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
 {
        u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
@@ -1088,7 +1160,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
        u16 flags = 0;
        unsigned in_index;
 
-       if (ATA_PROT_DMA != qc->tf.protocol)
+       if (qc->tf.protocol != ATA_PROT_DMA)
                return;
 
        /* Fill in command request block
@@ -1097,10 +1169,10 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
                flags |= CRQB_FLAG_READ;
        WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
        flags |= qc->tag << CRQB_TAG_SHIFT;
+       flags |= qc->tag << CRQB_IOID_SHIFT;    /* 50xx appears to ignore this*/
 
-       /* get current queue index from hardware */
-       in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
-                       >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+       /* get current queue index from software */
+       in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
 
        pp->crqb[in_index].sg_addr =
                cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
@@ -1180,7 +1252,7 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
        unsigned in_index;
        u32 flags = 0;
 
-       if (ATA_PROT_DMA != qc->tf.protocol)
+       if (qc->tf.protocol != ATA_PROT_DMA)
                return;
 
        /* Fill in Gen IIE command request block
@@ -1190,10 +1262,11 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
 
        WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
        flags |= qc->tag << CRQB_TAG_SHIFT;
+       flags |= qc->tag << CRQB_IOID_SHIFT;    /* "I/O Id" is -really-
+                                                  what we use as our tag */
 
-       /* get current queue index from hardware */
-       in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
-                       >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+       /* get current queue index from software */
+       in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
 
        crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
        crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
@@ -1241,82 +1314,40 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
  */
 static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
 {
-       void __iomem *port_mmio = mv_ap_base(qc->ap);
-       struct mv_port_priv *pp = qc->ap->private_data;
-       unsigned in_index;
-       u32 in_ptr;
+       struct ata_port *ap = qc->ap;
+       void __iomem *port_mmio = mv_ap_base(ap);
+       struct mv_port_priv *pp = ap->private_data;
+       struct mv_host_priv *hpriv = ap->host->private_data;
+       u32 in_index;
 
-       if (ATA_PROT_DMA != qc->tf.protocol) {
+       if (qc->tf.protocol != ATA_PROT_DMA) {
                /* We're about to send a non-EDMA capable command to the
                 * port.  Turn off EDMA so there won't be problems accessing
                 * shadow block, etc registers.
                 */
-               mv_stop_dma(qc->ap);
+               mv_stop_dma(ap);
                return ata_qc_issue_prot(qc);
        }
 
-       in_ptr   = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
-       in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+       mv_start_dma(port_mmio, hpriv, pp);
+
+       in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
 
        /* until we do queuing, the queue should be empty at this point */
        WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
                >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
 
-       in_index = mv_inc_q_index(in_index);    /* now incr producer index */
+       pp->req_idx++;
 
-       mv_start_dma(port_mmio, pp);
+       in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
 
        /* and write the request in pointer to kick the EDMA to life */
-       in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
-       in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
-       writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+       writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
+                port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
 
        return 0;
 }
 
-/**
- *      mv_get_crpb_status - get status from most recently completed cmd
- *      @ap: ATA channel to manipulate
- *
- *      This routine is for use when the port is in DMA mode, when it
- *      will be using the CRPB (command response block) method of
- *      returning command completion information.  We check indices
- *      are good, grab status, and bump the response consumer index to
- *      prove that we're up to date.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static u8 mv_get_crpb_status(struct ata_port *ap)
-{
-       void __iomem *port_mmio = mv_ap_base(ap);
-       struct mv_port_priv *pp = ap->private_data;
-       unsigned out_index;
-       u32 out_ptr;
-       u8 ata_status;
-
-       out_ptr   = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
-       out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
-
-       ata_status = le16_to_cpu(pp->crpb[out_index].flags)
-                                       >> CRPB_FLAG_STATUS_SHIFT;
-
-       /* increment our consumer index... */
-       out_index = mv_inc_q_index(out_index);
-
-       /* and, until we do NCQ, there should only be 1 CRPB waiting */
-       WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
-               >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
-
-       /* write out our inc'd consumer index so EDMA knows we're caught up */
-       out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
-       out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
-       writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
-
-       /* Return ATA status register for completed CRPB */
-       return ata_status;
-}
-
 /**
  *      mv_err_intr - Handle error interrupts on the port
  *      @ap: ATA channel to manipulate
@@ -1331,30 +1362,191 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_err_intr(struct ata_port *ap, int reset_allowed)
+static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
 {
        void __iomem *port_mmio = mv_ap_base(ap);
-       u32 edma_err_cause, serr = 0;
+       u32 edma_err_cause, eh_freeze_mask, serr = 0;
+       struct mv_port_priv *pp = ap->private_data;
+       struct mv_host_priv *hpriv = ap->host->private_data;
+       unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
+       unsigned int action = 0, err_mask = 0;
+       struct ata_eh_info *ehi = &ap->eh_info;
 
-       edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+       ata_ehi_clear_desc(ehi);
 
-       if (EDMA_ERR_SERR & edma_err_cause) {
+       if (!edma_enabled) {
+               /* just a guess: do we need to do this? should we
+                * expand this, and do it in all cases?
+                */
                sata_scr_read(ap, SCR_ERROR, &serr);
                sata_scr_write_flush(ap, SCR_ERROR, serr);
        }
-       if (EDMA_ERR_SELF_DIS & edma_err_cause) {
-               struct mv_port_priv *pp = ap->private_data;
-               pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+
+       edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+       ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
+
+       /*
+        * all generations share these EDMA error cause bits
+        */
+
+       if (edma_err_cause & EDMA_ERR_DEV)
+               err_mask |= AC_ERR_DEV;
+       if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
+                       EDMA_ERR_CRBQ_PAR | EDMA_ERR_CRPB_PAR |
+                       EDMA_ERR_INTRL_PAR)) {
+               err_mask |= AC_ERR_ATA_BUS;
+               action |= ATA_EH_HARDRESET;
+               ata_ehi_push_desc(ehi, ", parity error");
+       }
+       if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
+               ata_ehi_hotplugged(ehi);
+               ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
+                       ", dev disconnect" : ", dev connect");
+       }
+
+       if (IS_GEN_I(hpriv)) {
+               eh_freeze_mask = EDMA_EH_FREEZE_5;
+
+               if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
+                       struct mv_port_priv *pp = ap->private_data;
+                       pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+                       ata_ehi_push_desc(ehi, ", EDMA self-disable");
+               }
+       } else {
+               eh_freeze_mask = EDMA_EH_FREEZE;
+
+               if (edma_err_cause & EDMA_ERR_SELF_DIS) {
+                       struct mv_port_priv *pp = ap->private_data;
+                       pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+                       ata_ehi_push_desc(ehi, ", EDMA self-disable");
+               }
+
+               if (edma_err_cause & EDMA_ERR_SERR) {
+                       sata_scr_read(ap, SCR_ERROR, &serr);
+                       sata_scr_write_flush(ap, SCR_ERROR, serr);
+                       err_mask = AC_ERR_ATA_BUS;
+                       action |= ATA_EH_HARDRESET;
+               }
        }
-       DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
-               "SERR: 0x%08x\n", ap->print_id, edma_err_cause, serr);
 
        /* Clear EDMA now that SERR cleanup done */
        writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
-       /* check for fatal here and recover if needed */
-       if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause))
-               mv_stop_and_reset(ap);
+       if (!err_mask) {
+               err_mask = AC_ERR_OTHER;
+               action |= ATA_EH_HARDRESET;
+       }
+
+       ehi->serror |= serr;
+       ehi->action |= action;
+
+       if (qc)
+               qc->err_mask |= err_mask;
+       else
+               ehi->err_mask |= err_mask;
+
+       if (edma_err_cause & eh_freeze_mask)
+               ata_port_freeze(ap);
+       else
+               ata_port_abort(ap);
+}
+
+static void mv_intr_pio(struct ata_port *ap)
+{
+       struct ata_queued_cmd *qc;
+       u8 ata_status;
+
+       /* ignore spurious intr if drive still BUSY */
+       ata_status = readb(ap->ioaddr.status_addr);
+       if (unlikely(ata_status & ATA_BUSY))
+               return;
+
+       /* get active ATA command */
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+       if (unlikely(!qc))                      /* no active tag */
+               return;
+       if (qc->tf.flags & ATA_TFLAG_POLLING)   /* polling; we don't own qc */
+               return;
+
+       /* and finally, complete the ATA command */
+       qc->err_mask |= ac_err_mask(ata_status);
+       ata_qc_complete(qc);
+}
+
+static void mv_intr_edma(struct ata_port *ap)
+{
+       void __iomem *port_mmio = mv_ap_base(ap);
+       struct mv_host_priv *hpriv = ap->host->private_data;
+       struct mv_port_priv *pp = ap->private_data;
+       struct ata_queued_cmd *qc;
+       u32 out_index, in_index;
+       bool work_done = false;
+
+       /* get h/w response queue pointer */
+       in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
+                       >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+       while (1) {
+               u16 status;
+
+               /* get s/w response queue last-read pointer, and compare */
+               out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK;
+               if (in_index == out_index)
+                       break;
+
+                
+               /* 50xx: get active ATA command */
+               if (IS_GEN_I(hpriv)) 
+                       qc = ata_qc_from_tag(ap, ap->active_tag);
+
+               /* 60xx: get active ATA command via tag, to enable support
+                * for queueing.  this works transparently for queued and
+                * non-queued modes.
+                */
+               else {
+                       unsigned int tag;
+
+                       if (IS_GEN_II(hpriv))
+                               tag = (le16_to_cpu(pp->crpb[out_index].id)
+                                       >> CRPB_IOID_SHIFT_6) & 0x3f;
+                       else
+                               tag = (le16_to_cpu(pp->crpb[out_index].id)
+                                       >> CRPB_IOID_SHIFT_7) & 0x3f;
+
+                       qc = ata_qc_from_tag(ap, tag);
+               }
+
+               /* lower 8 bits of status are EDMA_ERR_IRQ_CAUSE_OFS
+                * bits (WARNING: might not necessarily be associated
+                * with this command), which -should- be clear
+                * if all is well
+                */
+               status = le16_to_cpu(pp->crpb[out_index].flags);
+               if (unlikely(status & 0xff)) {
+                       mv_err_intr(ap, qc);
+                       return;
+               }
+
+               /* and finally, complete the ATA command */
+               if (qc) {
+                       qc->err_mask |=
+                               ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT);
+                       ata_qc_complete(qc);
+               }
+
+               /* advance software response queue pointer, to 
+                * indicate (after the loop completes) to hardware
+                * that we have consumed a response queue entry.
+                */
+               work_done = true;
+               pp->resp_idx++;
+       }
+
+       if (work_done)
+               writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
+                        (out_index << EDMA_RSP_Q_PTR_SHIFT),
+                        port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
 }
 
 /**
@@ -1377,10 +1569,8 @@ static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
 {
        void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
        void __iomem *hc_mmio = mv_hc_base(mmio, hc);
-       struct ata_queued_cmd *qc;
        u32 hc_irq_cause;
-       int shift, port, port0, hard_port, handled;
-       unsigned int err_mask;
+       int port, port0;
 
        if (hc == 0)
                port0 = 0;
@@ -1389,79 +1579,95 @@ static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
 
        /* we'll need the HC success int register in most cases */
        hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
-       if (hc_irq_cause)
-               writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+       if (!hc_irq_cause)
+               return;
+
+       writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
 
        VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
                hc,relevant,hc_irq_cause);
 
        for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
-               u8 ata_status = 0;
                struct ata_port *ap = host->ports[port];
                struct mv_port_priv *pp = ap->private_data;
+               int have_err_bits, hard_port, shift;
+
+               if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
+                       continue;
+
+               shift = port << 1;              /* (port * 2) */
+               if (port >= MV_PORTS_PER_HC) {
+                       shift++;        /* skip bit 8 in the HC Main IRQ reg */
+               }
+               have_err_bits = ((PORT0_ERR << shift) & relevant);
+
+               if (unlikely(have_err_bits)) {
+                       struct ata_queued_cmd *qc;
+
+                       qc = ata_qc_from_tag(ap, ap->active_tag);
+                       if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
+                               continue;
+
+                       mv_err_intr(ap, qc);
+                       continue;
+               }
 
                hard_port = mv_hardport_from_port(port); /* range 0..3 */
-               handled = 0;    /* ensure ata_status is set if handled++ */
 
-               /* Note that DEV_IRQ might happen spuriously during EDMA,
-                * and should be ignored in such cases.
-                * The cause of this is still under investigation.
-                */
                if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
-                       /* EDMA: check for response queue interrupt */
-                       if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
-                               ata_status = mv_get_crpb_status(ap);
-                               handled = 1;
-                       }
+                       if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
+                               mv_intr_edma(ap);
                } else {
-                       /* PIO: check for device (drive) interrupt */
-                       if ((DEV_IRQ << hard_port) & hc_irq_cause) {
-                               ata_status = readb(ap->ioaddr.status_addr);
-                               handled = 1;
-                               /* ignore spurious intr if drive still BUSY */
-                               if (ata_status & ATA_BUSY) {
-                                       ata_status = 0;
-                                       handled = 0;
-                               }
-                       }
+                       if ((DEV_IRQ << hard_port) & hc_irq_cause)
+                               mv_intr_pio(ap);
                }
+       }
+       VPRINTK("EXIT\n");
+}
 
-               if (ap && (ap->flags & ATA_FLAG_DISABLED))
-                       continue;
+static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
+{
+       struct ata_port *ap;
+       struct ata_queued_cmd *qc;
+       struct ata_eh_info *ehi;
+       unsigned int i, err_mask, printed = 0;
+       u32 err_cause;
 
-               err_mask = ac_err_mask(ata_status);
+       err_cause = readl(mmio + PCI_IRQ_CAUSE_OFS);
 
-               shift = port << 1;              /* (port * 2) */
-               if (port >= MV_PORTS_PER_HC) {
-                       shift++;        /* skip bit 8 in the HC Main IRQ reg */
-               }
-               if ((PORT0_ERR << shift) & relevant) {
-                       mv_err_intr(ap, 1);
-                       err_mask |= AC_ERR_OTHER;
-                       handled = 1;
-               }
+       dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
+                  err_cause);
 
-               if (handled) {
+       DPRINTK("All regs @ PCI error\n");
+       mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
+
+       writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+
+       for (i = 0; i < host->n_ports; i++) {
+               ap = host->ports[i];
+               if (!ata_port_offline(ap)) {
+                       ehi = &ap->eh_info;
+                       ata_ehi_clear_desc(ehi);
+                       if (!printed++)
+                               ata_ehi_push_desc(ehi,
+                                       "PCI err cause 0x%08x", err_cause);
+                       err_mask = AC_ERR_HOST_BUS;
+                       ehi->action = ATA_EH_HARDRESET;
                        qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
-                               VPRINTK("port %u IRQ found for qc, "
-                                       "ata_status 0x%x\n", port,ata_status);
-                               /* mark qc status appropriately */
-                               if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
-                                       qc->err_mask |= err_mask;
-                                       ata_qc_complete(qc);
-                               }
-                       }
+                       if (qc)
+                               qc->err_mask |= err_mask;
+                       else
+                               ehi->err_mask |= err_mask;
+
+                       ata_port_freeze(ap);
                }
        }
-       VPRINTK("EXIT\n");
 }
 
 /**
- *      mv_interrupt -
+ *      mv_interrupt - Main interrupt event handler
  *      @irq: unused
  *      @dev_instance: private data; in this case the host structure
- *      @regs: unused
  *
  *      Read the read only register to determine if any host
  *      controllers have pending interrupts.  If so, call lower level
@@ -1477,7 +1683,6 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
        struct ata_host *host = dev_instance;
        unsigned int hc, handled = 0, n_hcs;
        void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
-       struct mv_host_priv *hpriv;
        u32 irq_stat;
 
        irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
@@ -1491,34 +1696,21 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
        n_hcs = mv_get_hc_count(host->ports[0]->flags);
        spin_lock(&host->lock);
 
+       if (unlikely(irq_stat & PCI_ERR)) {
+               mv_pci_error(host, mmio);
+               handled = 1;
+               goto out_unlock;        /* skip all other HC irq handling */
+       }
+
        for (hc = 0; hc < n_hcs; hc++) {
                u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
                if (relevant) {
                        mv_host_intr(host, relevant, hc);
-                       handled++;
-               }
-       }
-
-       hpriv = host->private_data;
-       if (IS_60XX(hpriv)) {
-               /* deal with the interrupt coalescing bits */
-               if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) {
-                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO);
-                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI);
-                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE);
+                       handled = 1;
                }
        }
 
-       if (PCI_ERR & irq_stat) {
-               printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
-                      readl(mmio + PCI_IRQ_CAUSE_OFS));
-
-               DPRINTK("All regs @ PCI error\n");
-               mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
-
-               writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
-               handled++;
-       }
+out_unlock:
        spin_unlock(&host->lock);
 
        return IRQ_RETVAL(handled);
@@ -1573,12 +1765,9 @@ static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
 
 static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
 {
-       u8 rev_id;
        int early_5080;
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
-       early_5080 = (pdev->device == 0x5080) && (rev_id == 0);
+       early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
 
        if (!early_5080) {
                u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
@@ -1907,7 +2096,7 @@ static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
 
        writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
 
-       if (IS_60XX(hpriv)) {
+       if (IS_GEN_II(hpriv)) {
                u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
                ifctl |= (1 << 7);              /* enable gen2i speed */
                ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
@@ -1923,32 +2112,12 @@ static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
 
        hpriv->ops->phy_errata(hpriv, mmio, port_no);
 
-       if (IS_50XX(hpriv))
+       if (IS_GEN_I(hpriv))
                mdelay(1);
 }
 
-static void mv_stop_and_reset(struct ata_port *ap)
-{
-       struct mv_host_priv *hpriv = ap->host->private_data;
-       void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
-
-       mv_stop_dma(ap);
-
-       mv_channel_reset(hpriv, mmio, ap->port_no);
-
-       __mv_phy_reset(ap, 0);
-}
-
-static inline void __msleep(unsigned int msec, int can_sleep)
-{
-       if (can_sleep)
-               msleep(msec);
-       else
-               mdelay(msec);
-}
-
 /**
- *      __mv_phy_reset - Perform eDMA reset followed by COMRESET
+ *      mv_phy_reset - Perform eDMA reset followed by COMRESET
  *      @ap: ATA channel to manipulate
  *
  *      Part of this is taken from __sata_phy_reset and modified to
@@ -1958,14 +2127,12 @@ static inline void __msleep(unsigned int msec, int can_sleep)
  *      Inherited from caller.  This is coded to safe to call at
  *      interrupt level, i.e. it does not sleep.
  */
-static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
+static void mv_phy_reset(struct ata_port *ap, unsigned int *class,
+                        unsigned long deadline)
 {
        struct mv_port_priv *pp = ap->private_data;
        struct mv_host_priv *hpriv = ap->host->private_data;
        void __iomem *port_mmio = mv_ap_base(ap);
-       struct ata_taskfile tf;
-       struct ata_device *dev = &ap->device[0];
-       unsigned long timeout;
        int retry = 5;
        u32 sstatus;
 
@@ -1978,22 +2145,21 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
        /* Issue COMRESET via SControl */
 comreset_retry:
        sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
-       __msleep(1, can_sleep);
+       msleep(1);
 
        sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
-       __msleep(20, can_sleep);
+       msleep(20);
 
-       timeout = jiffies + msecs_to_jiffies(200);
        do {
                sata_scr_read(ap, SCR_STATUS, &sstatus);
                if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
                        break;
 
-               __msleep(1, can_sleep);
-       } while (time_before(jiffies, timeout));
+               msleep(1);
+       } while (time_before(jiffies, deadline));
 
        /* work around errata */
-       if (IS_60XX(hpriv) &&
+       if (IS_GEN_II(hpriv) &&
            (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
            (retry-- > 0))
                goto comreset_retry;
@@ -2002,13 +2168,8 @@ comreset_retry:
                "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
                mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
 
-       if (ata_port_online(ap)) {
-               ata_port_probe(ap);
-       } else {
-               sata_scr_read(ap, SCR_STATUS, &sstatus);
-               ata_port_printk(ap, KERN_INFO,
-                               "no device found (phy stat %08x)\n", sstatus);
-               ata_port_disable(ap);
+       if (ata_port_offline(ap)) {
+               *class = ATA_DEV_NONE;
                return;
        }
 
@@ -2022,68 +2183,152 @@ comreset_retry:
                u8 drv_stat = ata_check_status(ap);
                if ((drv_stat != 0x80) && (drv_stat != 0x7f))
                        break;
-               __msleep(500, can_sleep);
+               msleep(500);
                if (retry-- <= 0)
                        break;
+               if (time_after(jiffies, deadline))
+                       break;
        }
 
-       tf.lbah = readb(ap->ioaddr.lbah_addr);
-       tf.lbam = readb(ap->ioaddr.lbam_addr);
-       tf.lbal = readb(ap->ioaddr.lbal_addr);
-       tf.nsect = readb(ap->ioaddr.nsect_addr);
+       /* FIXME: if we passed the deadline, the following
+        * code probably produces an invalid result
+        */
 
-       dev->class = ata_dev_classify(&tf);
-       if (!ata_dev_enabled(dev)) {
-               VPRINTK("Port disabled post-sig: No device present.\n");
-               ata_port_disable(ap);
-       }
+       /* finally, read device signature from TF registers */
+       *class = ata_dev_try_classify(ap, 0, NULL);
 
        writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
-       pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+       WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
 
        VPRINTK("EXIT\n");
 }
 
-static void mv_phy_reset(struct ata_port *ap)
+static int mv_prereset(struct ata_port *ap, unsigned long deadline)
 {
-       __mv_phy_reset(ap, 1);
+       struct mv_port_priv *pp = ap->private_data;
+       struct ata_eh_context *ehc = &ap->eh_context;
+       int rc;
+       
+       rc = mv_stop_dma(ap);
+       if (rc)
+               ehc->i.action |= ATA_EH_HARDRESET;
+
+       if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
+               pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
+               ehc->i.action |= ATA_EH_HARDRESET;
+       }
+
+       /* if we're about to do hardreset, nothing more to do */
+       if (ehc->i.action & ATA_EH_HARDRESET)
+               return 0;
+
+       if (ata_port_online(ap))
+               rc = ata_wait_ready(ap, deadline);
+       else
+               rc = -ENODEV;
+
+       return rc;
 }
 
-/**
- *      mv_eng_timeout - Routine called by libata when SCSI times out I/O
- *      @ap: ATA channel to manipulate
- *
- *      Intent is to clear all pending error conditions, reset the
- *      chip/bus, fail the command, and move on.
- *
- *      LOCKING:
- *      This routine holds the host lock while failing the command.
- */
-static void mv_eng_timeout(struct ata_port *ap)
+static int mv_hardreset(struct ata_port *ap, unsigned int *class,
+                       unsigned long deadline)
 {
+       struct mv_host_priv *hpriv = ap->host->private_data;
        void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
-       struct ata_queued_cmd *qc;
-       unsigned long flags;
 
-       ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
-       DPRINTK("All regs @ start of eng_timeout\n");
-       mv_dump_all_regs(mmio, ap->port_no, to_pci_dev(ap->host->dev));
+       mv_stop_dma(ap);
 
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-        printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
-              mmio, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd);
+       mv_channel_reset(hpriv, mmio, ap->port_no);
 
-       spin_lock_irqsave(&ap->host->lock, flags);
-       mv_err_intr(ap, 0);
-       mv_stop_and_reset(ap);
-       spin_unlock_irqrestore(&ap->host->lock, flags);
+       mv_phy_reset(ap, class, deadline);
 
-       WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
-       if (qc->flags & ATA_QCFLAG_ACTIVE) {
-               qc->err_mask |= AC_ERR_TIMEOUT;
-               ata_eh_qc_complete(qc);
+       return 0;
+}
+
+static void mv_postreset(struct ata_port *ap, unsigned int *classes)
+{
+       u32 serr;
+
+       /* print link status */
+       sata_print_link_status(ap);
+
+       /* clear SError */
+       sata_scr_read(ap, SCR_ERROR, &serr);
+       sata_scr_write_flush(ap, SCR_ERROR, serr);
+
+       /* bail out if no device is present */
+       if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+               DPRINTK("EXIT, no device\n");
+               return;
        }
+
+       /* set up device control */
+       iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+}
+
+static void mv_error_handler(struct ata_port *ap)
+{
+       ata_do_eh(ap, mv_prereset, ata_std_softreset,
+                 mv_hardreset, mv_postreset);
+}
+
+static void mv_post_int_cmd(struct ata_queued_cmd *qc)
+{
+       mv_stop_dma(qc->ap);
+}
+
+static void mv_eh_freeze(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+       unsigned int hc = (ap->port_no > 3) ? 1 : 0;
+       u32 tmp, mask;
+       unsigned int shift;
+
+       /* FIXME: handle coalescing completion events properly */
+
+       shift = ap->port_no * 2;
+       if (hc > 0)
+               shift++;
+
+       mask = 0x3 << shift;
+
+       /* disable assertion of portN err, done events */
+       tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
+       writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS);
+}
+
+static void mv_eh_thaw(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+       unsigned int hc = (ap->port_no > 3) ? 1 : 0;
+       void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+       void __iomem *port_mmio = mv_ap_base(ap);
+       u32 tmp, mask, hc_irq_cause;
+       unsigned int shift, hc_port_no = ap->port_no;
+
+       /* FIXME: handle coalescing completion events properly */
+
+       shift = ap->port_no * 2;
+       if (hc > 0) {
+               shift++;
+               hc_port_no -= 4;
+       }
+
+       mask = 0x3 << shift;
+
+       /* clear EDMA errors on this port */
+       writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+       /* clear pending irq events */
+       hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+       hc_irq_cause &= ~(1 << hc_port_no);     /* clear CRPB-done */
+       hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */
+       writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+
+       /* enable assertion of portN err, done events */
+       tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
+       writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS);
 }
 
 /**
@@ -2139,17 +2384,14 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
 {
        struct pci_dev *pdev = to_pci_dev(host->dev);
        struct mv_host_priv *hpriv = host->private_data;
-       u8 rev_id;
        u32 hp_flags = hpriv->hp_flags;
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
        switch(board_idx) {
        case chip_5080:
                hpriv->ops = &mv5xxx_ops;
-               hp_flags |= MV_HP_50XX;
+               hp_flags |= MV_HP_GEN_I;
 
-               switch (rev_id) {
+               switch (pdev->revision) {
                case 0x1:
                        hp_flags |= MV_HP_ERRATA_50XXB0;
                        break;
@@ -2167,9 +2409,9 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
        case chip_504x:
        case chip_508x:
                hpriv->ops = &mv5xxx_ops;
-               hp_flags |= MV_HP_50XX;
+               hp_flags |= MV_HP_GEN_I;
 
-               switch (rev_id) {
+               switch (pdev->revision) {
                case 0x0:
                        hp_flags |= MV_HP_ERRATA_50XXB0;
                        break;
@@ -2187,8 +2429,9 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
        case chip_604x:
        case chip_608x:
                hpriv->ops = &mv6xxx_ops;
+               hp_flags |= MV_HP_GEN_II;
 
-               switch (rev_id) {
+               switch (pdev->revision) {
                case 0x7:
                        hp_flags |= MV_HP_ERRATA_60X1B2;
                        break;
@@ -2206,10 +2449,9 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
        case chip_7042:
        case chip_6042:
                hpriv->ops = &mv6xxx_ops;
-
                hp_flags |= MV_HP_GEN_IIE;
 
-               switch (rev_id) {
+               switch (pdev->revision) {
                case 0x0:
                        hp_flags |= MV_HP_ERRATA_XX42A0;
                        break;
@@ -2273,7 +2515,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
        hpriv->ops->enable_leds(hpriv, mmio);
 
        for (port = 0; port < host->n_ports; port++) {
-               if (IS_60XX(hpriv)) {
+               if (IS_GEN_II(hpriv)) {
                        void __iomem *port_mmio = mv_port_base(mmio, port);
 
                        u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
@@ -2308,7 +2550,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
        /* and unmask interrupt generation for host regs */
        writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
 
-       if (IS_50XX(hpriv))
+       if (IS_GEN_I(hpriv))
                writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
        else
                writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
@@ -2337,14 +2579,12 @@ static void mv_print_info(struct ata_host *host)
 {
        struct pci_dev *pdev = to_pci_dev(host->dev);
        struct mv_host_priv *hpriv = host->private_data;
-       u8 rev_id, scc;
+       u8 scc;
        const char *scc_s, *gen;
 
        /* Use this to determine the HW stepping of the chip so we know
         * what errata to workaround
         */
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
        pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
        if (scc == 0)
                scc_s = "SCSI";
@@ -2426,8 +2666,9 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        mv_print_info(host);
 
        pci_set_master(pdev);
+       pci_set_mwi(pdev);
        return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
-                                &mv_sht);
+                                IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
 }
 
 static int __init mv_init(void)
index b2656867c64711075e77478bf6186f9cd0b81b57..db81e3efa5ec4f03c3d8ab7888a07bd632cb3589 100644 (file)
@@ -1560,7 +1560,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        ppi[0] = &nv_port_info[type];
-       rc = ata_pci_prepare_native_host(pdev, ppi, &host);
+       rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
        if (rc)
                return rc;
 
index 2ad5872fe90c2deaea8270ff8a7e51295270637b..d2fcb9a6bec2a024ef4a2dcbb9369cf592618d31 100644 (file)
@@ -45,7 +45,7 @@
 #include "sata_promise.h"
 
 #define DRV_NAME       "sata_promise"
-#define DRV_VERSION    "2.08"
+#define DRV_VERSION    "2.09"
 
 enum {
        PDC_MAX_PORTS           = 4,
@@ -716,6 +716,9 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
        unsigned int i, tmp;
        unsigned int handled = 0;
        void __iomem *mmio_base;
+       unsigned int hotplug_offset, ata_no;
+       u32 hotplug_status;
+       int is_sataii_tx4;
 
        VPRINTK("ENTER\n");
 
@@ -726,10 +729,20 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
 
        mmio_base = host->iomap[PDC_MMIO_BAR];
 
+       /* read and clear hotplug flags for all ports */
+       if (host->ports[0]->flags & PDC_FLAG_GEN_II)
+               hotplug_offset = PDC2_SATA_PLUG_CSR;
+       else
+               hotplug_offset = PDC_SATA_PLUG_CSR;
+       hotplug_status = readl(mmio_base + hotplug_offset);
+       if (hotplug_status & 0xff)
+               writel(hotplug_status | 0xff, mmio_base + hotplug_offset);
+       hotplug_status &= 0xff; /* clear uninteresting bits */
+
        /* reading should also clear interrupts */
        mask = readl(mmio_base + PDC_INT_SEQMASK);
 
-       if (mask == 0xffffffff) {
+       if (mask == 0xffffffff && hotplug_status == 0) {
                VPRINTK("QUICK EXIT 2\n");
                return IRQ_NONE;
        }
@@ -737,16 +750,34 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
        spin_lock(&host->lock);
 
        mask &= 0xffff;         /* only 16 tags possible */
-       if (!mask) {
+       if (mask == 0 && hotplug_status == 0) {
                VPRINTK("QUICK EXIT 3\n");
                goto done_irq;
        }
 
        writel(mask, mmio_base + PDC_INT_SEQMASK);
 
+       is_sataii_tx4 = pdc_is_sataii_tx4(host->ports[0]->flags);
+
        for (i = 0; i < host->n_ports; i++) {
                VPRINTK("port %u\n", i);
                ap = host->ports[i];
+
+               /* check for a plug or unplug event */
+               ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
+               tmp = hotplug_status & (0x11 << ata_no);
+               if (tmp && ap &&
+                   !(ap->flags & ATA_FLAG_DISABLED)) {
+                       struct ata_eh_info *ehi = &ap->eh_info;
+                       ata_ehi_clear_desc(ehi);
+                       ata_ehi_hotplugged(ehi);
+                       ata_ehi_push_desc(ehi, "hotplug_status %#x", tmp);
+                       ata_port_freeze(ap);
+                       ++handled;
+                       continue;
+               }
+
+               /* check for a packet interrupt */
                tmp = mask & (1 << (i + 1));
                if (tmp && ap &&
                    !(ap->flags & ATA_FLAG_DISABLED)) {
@@ -902,9 +933,9 @@ static void pdc_host_init(struct ata_host *host)
        tmp = readl(mmio + hotplug_offset);
        writel(tmp | 0xff, mmio + hotplug_offset);
 
-       /* mask plug/unplug ints */
+       /* unmask plug/unplug ints */
        tmp = readl(mmio + hotplug_offset);
-       writel(tmp 0xff0000, mmio + hotplug_offset);
+       writel(tmp & ~0xff0000, mmio + hotplug_offset);
 
        /* don't initialise TBG or SLEW on 2nd generation chips */
        if (is_gen2)
index fd80bcf1b236c1179b777ebb5e3305693a84c965..33716b00c6b7ec1de843a36772303a035e52ed31 100644 (file)
@@ -334,7 +334,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                break;
        }
 
-       rc = ata_pci_prepare_native_host(pdev, ppi, &host);
+       rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
        if (rc)
                return rc;
 
index aca71819f6e8cfd35c6a5af8f4a9a7bdab5dace1..b52f83ab056ac30256ef2b9c6d75831fdf9efc52 100644 (file)
@@ -213,7 +213,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        host->private_data = hpriv;
 
        /* the first two ports are standard SFF */
-       rc = ata_pci_init_native_host(host);
+       rc = ata_pci_init_sff_host(host);
        if (rc)
                return rc;
 
index a4c0832033d8cc3145c75d5bd050916564129251..c4124475f754f101fc427a63934901d59de9083b 100644 (file)
@@ -412,7 +412,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
        struct ata_host *host;
        int rc;
 
-       rc = ata_pci_prepare_native_host(pdev, ppi, &host);
+       rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
        if (rc)
                return rc;
        *r_host = host;
index 0d3a38b1cb0b221db91c2e3d27aad589b8d1dac4..77637e780d4150eee9713b7117e0fd0adcdb1573 100644 (file)
@@ -1704,7 +1704,6 @@ static int __devinit eni_do_init(struct atm_dev *dev)
        struct pci_dev *pci_dev;
        unsigned long real_base;
        void __iomem *base;
-       unsigned char revision;
        int error,i,last;
 
        DPRINTK(">eni_init\n");
@@ -1715,12 +1714,6 @@ static int __devinit eni_do_init(struct atm_dev *dev)
        pci_dev = eni_dev->pci_dev;
        real_base = pci_resource_start(pci_dev, 0);
        eni_dev->irq = pci_dev->irq;
-       error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision);
-       if (error) {
-               printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%02x\n",
-                   dev->number,error);
-               return -EINVAL;
-       }
        if ((error = pci_write_config_word(pci_dev,PCI_COMMAND,
            PCI_COMMAND_MEMORY |
            (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
@@ -1729,7 +1722,7 @@ static int __devinit eni_do_init(struct atm_dev *dev)
                return -EIO;
        }
        printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,",
-           dev->number,revision,real_base,eni_dev->irq);
+           dev->number,pci_dev->revision,real_base,eni_dev->irq);
        if (!(base = ioremap_nocache(real_base,MAP_MAX_SIZE))) {
                printk("\n");
                printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page "
index 3800bc0cb2efe8d9016f54fd19e007096cda1842..8f995ce8d73b460a7fb88e25d70d05298477a483 100644 (file)
@@ -3679,7 +3679,6 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
        unsigned long membase, srambase;
        struct idt77252_dev *card;
        struct atm_dev *dev;
-       ushort revision = 0;
        int i, err;
 
 
@@ -3688,19 +3687,13 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
                return err;
        }
 
-       if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) {
-               printk("idt77252-%d: can't read PCI_REVISION_ID\n", index);
-               err = -ENODEV;
-               goto err_out_disable_pdev;
-       }
-
        card = kzalloc(sizeof(struct idt77252_dev), GFP_KERNEL);
        if (!card) {
                printk("idt77252-%d: can't allocate private data\n", index);
                err = -ENOMEM;
                goto err_out_disable_pdev;
        }
-       card->revision = revision;
+       card->revision = pcidev->revision;
        card->index = index;
        card->pcidev = pcidev;
        sprintf(card->name, "idt77252-%d", card->index);
@@ -3762,8 +3755,8 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
        }
 
        printk("%s: ABR SAR (Rev %c): MEM %08lx SRAM %08lx [%u KB]\n",
-              card->name, ((revision > 1) && (revision < 25)) ?
-              'A' + revision - 1 : '?', membase, srambase,
+              card->name, ((card->revision > 1) && (card->revision < 25)) ?
+              'A' + card->revision - 1 : '?', membase, srambase,
               card->sramsize / 1024);
 
        if (init_card(dev)) {
index bb7ef570514cd660e2a200af09647bbebd97a416..a3b605a0ca17a47e106359e4299d5db2e70515df 100644 (file)
@@ -2290,7 +2290,6 @@ static int __devinit ia_init(struct atm_dev *dev)
        unsigned long real_base;
        void __iomem *base;
        unsigned short command;  
-       unsigned char revision;  
        int error, i; 
          
        /* The device has been identified and registered. Now we read   
@@ -2305,16 +2304,14 @@ static int __devinit ia_init(struct atm_dev *dev)
        real_base = pci_resource_start (iadev->pci, 0);
        iadev->irq = iadev->pci->irq;
                  
-       if ((error = pci_read_config_word(iadev->pci, PCI_COMMAND,&command))   
-                   || (error = pci_read_config_byte(iadev->pci,   
-                               PCI_REVISION_ID,&revision)))   
-       {  
+       error = pci_read_config_word(iadev->pci, PCI_COMMAND, &command);
+       if (error) {
                printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%x\n",  
                                dev->number,error);  
                return -EINVAL;  
        }  
        IF_INIT(printk(DEV_LABEL "(itf %d): rev.%d,realbase=0x%lx,irq=%d\n",  
-                       dev->number, revision, real_base, iadev->irq);)  
+                       dev->number, iadev->pci->revision, real_base, iadev->irq);)
          
        /* find mapping size of board */  
          
@@ -2353,7 +2350,7 @@ static int __devinit ia_init(struct atm_dev *dev)
                return error;  
        }  
        IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=%p,irq=%d\n",  
-                       dev->number, revision, base, iadev->irq);)  
+                       dev->number, iadev->pci->revision, base, iadev->irq);)
          
        /* filling the iphase dev structure */  
        iadev->mem = iadev->pci_map_size /2;  
index 09f477d4237a5f553d711748dab5ff953f3255b3..0e2c1ae650e7f9b4cfeb15342bd9a26ea9bfbf1d 100644 (file)
@@ -246,8 +246,8 @@ struct lanai_vcc {
 };
 
 enum lanai_type {
-       lanai2  = PCI_VENDOR_ID_EF_ATM_LANAI2,
-       lanaihb = PCI_VENDOR_ID_EF_ATM_LANAIHB
+       lanai2  = PCI_DEVICE_ID_EF_ATM_LANAI2,
+       lanaihb = PCI_DEVICE_ID_EF_ATM_LANAIHB
 };
 
 struct lanai_dev_stats {
@@ -293,7 +293,6 @@ struct lanai_dev {
        struct atm_vcc *cbrvcc;
        int number;
        int board_rev;
-       u8 pci_revision;
 /* TODO - look at race conditions with maintence of conf1/conf2 */
 /* TODO - transmit locking: should we use _irq not _irqsave? */
 /* TODO - organize above in some rational fashion (see <asm/cache.h>) */
@@ -1969,14 +1968,6 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai)
                    "(itf %d): No suitable DMA available.\n", lanai->number);
                return -EBUSY;
        }
-       /* Get the pci revision byte */
-       result = pci_read_config_byte(pci, PCI_REVISION_ID,
-           &lanai->pci_revision);
-       if (result != PCIBIOS_SUCCESSFUL) {
-               printk(KERN_ERR DEV_LABEL "(itf %d): can't read "
-                   "PCI_REVISION_ID: %d\n", lanai->number, result);
-               return -EINVAL;
-       }
        result = pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &w);
        if (result != PCIBIOS_SUCCESSFUL) {
                printk(KERN_ERR DEV_LABEL "(itf %d): can't read "
@@ -2254,7 +2245,7 @@ static int __devinit lanai_dev_open(struct atm_dev *atmdev)
        lanai_timed_poll_start(lanai);
        printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d, base=0x%lx, irq=%u "
            "(%02X-%02X-%02X-%02X-%02X-%02X)\n", lanai->number,
-           (int) lanai->pci_revision, (unsigned long) lanai->base,
+           (int) lanai->pci->revision, (unsigned long) lanai->base,
            lanai->pci->irq,
            atmdev->esi[0], atmdev->esi[1], atmdev->esi[2],
            atmdev->esi[3], atmdev->esi[4], atmdev->esi[5]);
@@ -2491,7 +2482,7 @@ static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page)
                    (unsigned int) lanai->magicno, lanai->num_vci);
        if (left-- == 0)
                return sprintf(page, "revision: board=%d, pci_if=%d\n",
-                   lanai->board_rev, (int) lanai->pci_revision);
+                   lanai->board_rev, (int) lanai->pci->revision);
        if (left-- == 0)
                return sprintf(page, "EEPROM ESI: "
                    "%02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -2631,14 +2622,8 @@ static int __devinit lanai_init_one(struct pci_dev *pci,
 }
 
 static struct pci_device_id lanai_pci_tbl[] = {
-       {
-               PCI_VENDOR_ID_EF, PCI_VENDOR_ID_EF_ATM_LANAI2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
-       },
-       {
-               PCI_VENDOR_ID_EF, PCI_VENDOR_ID_EF_ATM_LANAIHB,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
-       },
+       { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAI2) },
+       { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAIHB) },
        { 0, }  /* terminal entry */
 };
 MODULE_DEVICE_TABLE(pci, lanai_pci_tbl);
index 2ad2527cf5b324d47568e1411dd186ec5ea984ba..020a87a476c813945d1f1f1ffc55c398704dc502 100644 (file)
@@ -1182,7 +1182,6 @@ static int __devinit zatm_init(struct atm_dev *dev)
        struct zatm_dev *zatm_dev;
        struct pci_dev *pci_dev;
        unsigned short command;
-       unsigned char revision;
        int error,i,last;
        unsigned long t0,t1,t2;
 
@@ -1192,8 +1191,7 @@ static int __devinit zatm_init(struct atm_dev *dev)
        pci_dev = zatm_dev->pci_dev;
        zatm_dev->base = pci_resource_start(pci_dev, 0);
        zatm_dev->irq = pci_dev->irq;
-       if ((error = pci_read_config_word(pci_dev,PCI_COMMAND,&command)) ||
-           (error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision))) {
+       if ((error = pci_read_config_word(pci_dev,PCI_COMMAND,&command))) {
                printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%02x\n",
                    dev->number,error);
                return -EINVAL;
@@ -1206,7 +1204,7 @@ static int __devinit zatm_init(struct atm_dev *dev)
        }
        eprom_get_esi(dev);
        printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%x,irq=%d,",
-           dev->number,revision,zatm_dev->base,zatm_dev->irq);
+           dev->number,pci_dev->revision,zatm_dev->base,zatm_dev->irq);
        /* reset uPD98401 */
        zout(0,SWR);
        while (!(zin(GSR) & uPD98401_INT_IND));
index 1ec0654665cfd97098aabcb54e16e66ac8e1aa0b..7370d7cf59888050d374d7a48a03185a06f0df7c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 
 #include "base.h"
 
index 5512d84452f2d9a5c0bd9df4e4f06599b4e5aacf..47eb02d9f1afdc30489a9520ae44ba334a4bd9ea 100644 (file)
@@ -44,6 +44,6 @@ struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
 
 extern char *make_class_name(const char *name, struct kobject *kobj);
 
-extern void devres_release_all(struct device *dev);
+extern int devres_release_all(struct device *dev);
 
 extern struct kset devices_subsys;
index dca734819e50cc670439f22806eac6198e8c29eb..61c67526a656c29d05a1a1e93bba6f4e86872a14 100644 (file)
@@ -138,12 +138,24 @@ void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
        }
 }
 
-static struct kobj_type ktype_bus = {
+static struct kobj_type bus_ktype = {
        .sysfs_ops      = &bus_sysfs_ops,
+};
+
+static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
+{
+       struct kobj_type *ktype = get_ktype(kobj);
 
+       if (ktype == &bus_ktype)
+               return 1;
+       return 0;
+}
+
+static struct kset_uevent_ops bus_uevent_ops = {
+       .filter = bus_uevent_filter,
 };
 
-static decl_subsys(bus, &ktype_bus, NULL);
+static decl_subsys(bus, &bus_ktype, &bus_uevent_ops);
 
 
 #ifdef CONFIG_HOTPLUG
@@ -562,7 +574,6 @@ static int add_probe_files(struct bus_type *bus)
 
        bus->drivers_probe_attr.attr.name = "drivers_probe";
        bus->drivers_probe_attr.attr.mode = S_IWUSR;
-       bus->drivers_probe_attr.attr.owner = bus->owner;
        bus->drivers_probe_attr.store = store_drivers_probe;
        retval = bus_create_file(bus, &bus->drivers_probe_attr);
        if (retval)
@@ -570,7 +581,6 @@ static int add_probe_files(struct bus_type *bus)
 
        bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe";
        bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO;
-       bus->drivers_autoprobe_attr.attr.owner = bus->owner;
        bus->drivers_autoprobe_attr.show = show_drivers_autoprobe;
        bus->drivers_autoprobe_attr.store = store_drivers_autoprobe;
        retval = bus_create_file(bus, &bus->drivers_autoprobe_attr);
@@ -610,7 +620,8 @@ int bus_add_driver(struct device_driver *drv)
        if (error)
                goto out_put_bus;
        drv->kobj.kset = &bus->drivers;
-       if ((error = kobject_register(&drv->kobj)))
+       error = kobject_register(&drv->kobj);
+       if (error)
                goto out_put_bus;
 
        if (drv->bus->drivers_autoprobe) {
@@ -760,7 +771,8 @@ static int bus_add_attrs(struct bus_type * bus)
 
        if (bus->bus_attrs) {
                for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
-                       if ((error = bus_create_file(bus,&bus->bus_attrs[i])))
+                       error = bus_create_file(bus,&bus->bus_attrs[i]);
+                       if (error)
                                goto Err;
                }
        }
index 8c506dbe39138bc11b8901944a81461c5a424e79..4d2222618b780f47dfa54e40246dbd9e4c8bdcc7 100644 (file)
@@ -312,9 +312,6 @@ static void class_dev_release(struct kobject * kobj)
 
        pr_debug("device class '%s': release.\n", cd->class_id);
 
-       kfree(cd->devt_attr);
-       cd->devt_attr = NULL;
-
        if (cd->release)
                cd->release(cd);
        else if (cls->release)
@@ -547,6 +544,9 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
        return print_dev_t(buf, class_dev->devt);
 }
 
+static struct class_device_attribute class_devt_attr =
+       __ATTR(dev, S_IRUGO, show_dev, NULL);
+
 static ssize_t store_uevent(struct class_device *class_dev,
                            const char *buf, size_t count)
 {
@@ -554,6 +554,9 @@ static ssize_t store_uevent(struct class_device *class_dev,
        return count;
 }
 
+static struct class_device_attribute class_uevent_attr =
+       __ATTR(uevent, S_IWUSR, NULL, store_uevent);
+
 void class_device_initialize(struct class_device *class_dev)
 {
        kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -603,32 +606,15 @@ int class_device_add(struct class_device *class_dev)
                                  &parent_class->subsys.kobj, "subsystem");
        if (error)
                goto out3;
-       class_dev->uevent_attr.attr.name = "uevent";
-       class_dev->uevent_attr.attr.mode = S_IWUSR;
-       class_dev->uevent_attr.attr.owner = parent_class->owner;
-       class_dev->uevent_attr.store = store_uevent;
-       error = class_device_create_file(class_dev, &class_dev->uevent_attr);
+
+       error = class_device_create_file(class_dev, &class_uevent_attr);
        if (error)
                goto out3;
 
        if (MAJOR(class_dev->devt)) {
-               struct class_device_attribute *attr;
-               attr = kzalloc(sizeof(*attr), GFP_KERNEL);
-               if (!attr) {
-                       error = -ENOMEM;
-                       goto out4;
-               }
-               attr->attr.name = "dev";
-               attr->attr.mode = S_IRUGO;
-               attr->attr.owner = parent_class->owner;
-               attr->show = show_dev;
-               error = class_device_create_file(class_dev, attr);
-               if (error) {
-                       kfree(attr);
+               error = class_device_create_file(class_dev, &class_devt_attr);
+               if (error)
                        goto out4;
-               }
-
-               class_dev->devt_attr = attr;
        }
 
        error = class_device_add_attrs(class_dev);
@@ -671,10 +657,10 @@ int class_device_add(struct class_device *class_dev)
  out6:
        class_device_remove_attrs(class_dev);
  out5:
-       if (class_dev->devt_attr)
-               class_device_remove_file(class_dev, class_dev->devt_attr);
+       if (MAJOR(class_dev->devt))
+               class_device_remove_file(class_dev, &class_devt_attr);
  out4:
-       class_device_remove_file(class_dev, &class_dev->uevent_attr);
+       class_device_remove_file(class_dev, &class_uevent_attr);
  out3:
        kobject_del(&class_dev->kobj);
  out2:
@@ -774,9 +760,9 @@ void class_device_del(struct class_device *class_dev)
                sysfs_remove_link(&class_dev->kobj, "device");
        }
        sysfs_remove_link(&class_dev->kobj, "subsystem");
-       class_device_remove_file(class_dev, &class_dev->uevent_attr);
-       if (class_dev->devt_attr)
-               class_device_remove_file(class_dev, class_dev->devt_attr);
+       class_device_remove_file(class_dev, &class_uevent_attr);
+       if (MAJOR(class_dev->devt))
+               class_device_remove_file(class_dev, &class_devt_attr);
        class_device_remove_attrs(class_dev);
        class_device_remove_groups(class_dev);
 
index dd40d78a023dd1f2fde9712ac7700d5ade4893cf..0455aa78fa135cb04529efb281386d25423b2970 100644 (file)
@@ -310,6 +310,9 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
+static struct device_attribute uevent_attr =
+       __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
+
 static int device_add_attributes(struct device *dev,
                                 struct device_attribute *attrs)
 {
@@ -423,6 +426,9 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
        return print_dev_t(buf, dev->devt);
 }
 
+static struct device_attribute devt_attr =
+       __ATTR(dev, S_IRUGO, show_dev, NULL);
+
 /*
  *     devices_subsys - structure to be registered with kobject core.
  */
@@ -681,35 +687,14 @@ int device_add(struct device *dev)
                blocking_notifier_call_chain(&dev->bus->bus_notifier,
                                             BUS_NOTIFY_ADD_DEVICE, dev);
 
-       dev->uevent_attr.attr.name = "uevent";
-       dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR;
-       if (dev->driver)
-               dev->uevent_attr.attr.owner = dev->driver->owner;
-       dev->uevent_attr.store = store_uevent;
-       dev->uevent_attr.show = show_uevent;
-       error = device_create_file(dev, &dev->uevent_attr);
+       error = device_create_file(dev, &uevent_attr);
        if (error)
                goto attrError;
 
        if (MAJOR(dev->devt)) {
-               struct device_attribute *attr;
-               attr = kzalloc(sizeof(*attr), GFP_KERNEL);
-               if (!attr) {
-                       error = -ENOMEM;
-                       goto ueventattrError;
-               }
-               attr->attr.name = "dev";
-               attr->attr.mode = S_IRUGO;
-               if (dev->driver)
-                       attr->attr.owner = dev->driver->owner;
-               attr->show = show_dev;
-               error = device_create_file(dev, attr);
-               if (error) {
-                       kfree(attr);
+               error = device_create_file(dev, &devt_attr);
+               if (error)
                        goto ueventattrError;
-               }
-
-               dev->devt_attr = attr;
        }
 
        if (dev->class) {
@@ -733,11 +718,14 @@ int device_add(struct device *dev)
                }
        }
 
-       if ((error = device_add_attrs(dev)))
+       error = device_add_attrs(dev);
+       if (error)
                goto AttrsError;
-       if ((error = device_pm_add(dev)))
+       error = device_pm_add(dev);
+       if (error)
                goto PMError;
-       if ((error = bus_add_device(dev)))
+       error = bus_add_device(dev);
+       if (error)
                goto BusError;
        kobject_uevent(&dev->kobj, KOBJ_ADD);
        bus_attach_device(dev);
@@ -767,10 +755,8 @@ int device_add(struct device *dev)
                                             BUS_NOTIFY_DEL_DEVICE, dev);
        device_remove_attrs(dev);
  AttrsError:
-       if (dev->devt_attr) {
-               device_remove_file(dev, dev->devt_attr);
-               kfree(dev->devt_attr);
-       }
+       if (MAJOR(dev->devt))
+               device_remove_file(dev, &devt_attr);
 
        if (dev->class) {
                sysfs_remove_link(&dev->kobj, "subsystem");
@@ -792,7 +778,7 @@ int device_add(struct device *dev)
                }
        }
  ueventattrError:
-       device_remove_file(dev, &dev->uevent_attr);
+       device_remove_file(dev, &uevent_attr);
  attrError:
        kobject_uevent(&dev->kobj, KOBJ_REMOVE);
        kobject_del(&dev->kobj);
@@ -869,10 +855,8 @@ void device_del(struct device * dev)
 
        if (parent)
                klist_del(&dev->knode_parent);
-       if (dev->devt_attr) {
-               device_remove_file(dev, dev->devt_attr);
-               kfree(dev->devt_attr);
-       }
+       if (MAJOR(dev->devt))
+               device_remove_file(dev, &devt_attr);
        if (dev->class) {
                sysfs_remove_link(&dev->kobj, "subsystem");
                /* If this is not a "fake" compatible device, remove the
@@ -926,7 +910,7 @@ void device_del(struct device * dev)
                        up(&dev->class->sem);
                }
        }
-       device_remove_file(dev, &dev->uevent_attr);
+       device_remove_file(dev, &uevent_attr);
        device_remove_attrs(dev);
        bus_remove_device(dev);
 
index b0088b0efecdd1e5395e4104d23d0fe34dbb9a0d..7ac474db88c525f46a0846810ca5f384fa07b104 100644 (file)
@@ -281,24 +281,16 @@ int driver_attach(struct device_driver * drv)
        return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
 }
 
-/**
- *     device_release_driver - manually detach device from driver.
- *     @dev:   device.
- *
- *     Manually detach device from driver.
- *
+/*
  *     __device_release_driver() must be called with @dev->sem held.
- *     When called for a USB interface, @dev->parent->sem must be held
- *     as well.
+ *     When called for a USB interface, @dev->parent->sem must be held as well.
  */
-
 static void __device_release_driver(struct device * dev)
 {
        struct device_driver * drv;
 
-       drv = dev->driver;
+       drv = get_driver(dev->driver);
        if (drv) {
-               get_driver(drv);
                driver_sysfs_remove(dev);
                sysfs_remove_link(&dev->kobj, "driver");
                klist_remove(&dev->knode_driver);
@@ -318,6 +310,13 @@ static void __device_release_driver(struct device * dev)
        }
 }
 
+/**
+ *     device_release_driver - manually detach device from driver.
+ *     @dev:   device.
+ *
+ *     Manually detach device from driver.
+ *     When called for a USB interface, @dev->parent->sem must be held.
+ */
 void device_release_driver(struct device * dev)
 {
        /*
index e1c0730a3b995d246ad965330854e768f746ab65..e8beb8e5b6264232dbfc0ea2dc7ae95d76f5af64 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/device.h>
 #include <linux/module.h>
 
+#include "base.h"
+
 struct devres_node {
        struct list_head                entry;
        dr_release_t                    release;
index 89a5f4a5491391e2270069090f43c6e82b6ef601..53f0ee6f301663db0ff4b87b5500b39bcd74744b 100644 (file)
@@ -175,7 +175,7 @@ static ssize_t firmware_loading_store(struct device *dev,
 static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
 
 static ssize_t
-firmware_data_read(struct kobject *kobj,
+firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
                   char *buffer, loff_t offset, size_t count)
 {
        struct device *dev = to_dev(kobj);
@@ -240,7 +240,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
  *     the driver as a firmware image.
  **/
 static ssize_t
-firmware_data_write(struct kobject *kobj,
+firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr,
                    char *buffer, loff_t offset, size_t count)
 {
        struct device *dev = to_dev(kobj);
@@ -271,7 +271,7 @@ out:
 }
 
 static struct bin_attribute firmware_attr_data_tmpl = {
-       .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
+       .attr = {.name = "data", .mode = 0644},
        .size = 0,
        .read = firmware_data_read,
        .write = firmware_data_write,
index 05dc8764e7650170ceabfd9c7f0fc8223afd33ce..eb9f38d0aa58f3d13928923627d66512e3255c38 100644 (file)
  */
 
 #include <linux/device.h>
+#include <linux/mutex.h>
+
 #include "power.h"
 
 LIST_HEAD(dpm_active);
 LIST_HEAD(dpm_off);
 LIST_HEAD(dpm_off_irq);
 
-DECLARE_MUTEX(dpm_sem);
-DECLARE_MUTEX(dpm_list_sem);
+DEFINE_MUTEX(dpm_mtx);
+DEFINE_MUTEX(dpm_list_mtx);
 
 int (*platform_enable_wakeup)(struct device *dev, int is_on);
 
-
-/**
- *     device_pm_set_parent - Specify power dependency.
- *     @dev:           Device who needs power.
- *     @parent:        Device that supplies power.
- *
- *     This function is used to manually describe a power-dependency
- *     relationship. It may be used to specify a transversal relationship
- *     (where the power supplier is not the physical (or electrical)
- *     ancestor of a specific device.
- *     The effect of this is that the supplier will not be powered down
- *     before the power dependent.
- */
-
-void device_pm_set_parent(struct device * dev, struct device * parent)
-{
-       put_device(dev->power.pm_parent);
-       dev->power.pm_parent = get_device(parent);
-}
-EXPORT_SYMBOL_GPL(device_pm_set_parent);
-
-int device_pm_add(struct device * dev)
+int device_pm_add(struct device *dev)
 {
        int error;
 
        pr_debug("PM: Adding info for %s:%s\n",
                 dev->bus ? dev->bus->name : "No Bus",
                 kobject_name(&dev->kobj));
-       down(&dpm_list_sem);
+       mutex_lock(&dpm_list_mtx);
        list_add_tail(&dev->power.entry, &dpm_active);
-       device_pm_set_parent(dev, dev->parent);
-       if ((error = dpm_sysfs_add(dev)))
+       error = dpm_sysfs_add(dev);
+       if (error)
                list_del(&dev->power.entry);
-       up(&dpm_list_sem);
+       mutex_unlock(&dpm_list_mtx);
        return error;
 }
 
-void device_pm_remove(struct device * dev)
+void device_pm_remove(struct device *dev)
 {
        pr_debug("PM: Removing info for %s:%s\n",
                 dev->bus ? dev->bus->name : "No Bus",
                 kobject_name(&dev->kobj));
-       down(&dpm_list_sem);
+       mutex_lock(&dpm_list_mtx);
        dpm_sysfs_remove(dev);
-       put_device(dev->power.pm_parent);
        list_del_init(&dev->power.entry);
-       up(&dpm_list_sem);
+       mutex_unlock(&dpm_list_mtx);
 }
 
 
index fb3d35a9e101582563b357848617cd7539e65e3a..2760f25b3ac5794a3e4557b28266c8354af740f6 100644 (file)
@@ -14,12 +14,12 @@ extern void device_shutdown(void);
 /*
  * Used to synchronize global power management operations.
  */
-extern struct semaphore dpm_sem;
+extern struct mutex dpm_mtx;
 
 /*
  * Used to serialize changes to the dpm_* lists.
  */
-extern struct semaphore dpm_list_sem;
+extern struct mutex dpm_list_mtx;
 
 /*
  * The PM lists.
index a2c64188d7133fc95c31343592039f7ace18a64b..00fd84ae6e66f955855f39286b66632c50b0e3dc 100644 (file)
@@ -29,14 +29,6 @@ int resume_device(struct device * dev)
 
        down(&dev->sem);
 
-       if (dev->power.pm_parent
-                       && dev->power.pm_parent->power.power_state.event) {
-               dev_err(dev, "PM: resume from %d, parent %s still %d\n",
-                       dev->power.power_state.event,
-                       dev->power.pm_parent->bus_id,
-                       dev->power.pm_parent->power.power_state.event);
-       }
-
        if (dev->bus && dev->bus->resume) {
                dev_dbg(dev,"resuming\n");
                error = dev->bus->resume(dev);
@@ -80,7 +72,7 @@ static int resume_device_early(struct device * dev)
  */
 void dpm_resume(void)
 {
-       down(&dpm_list_sem);
+       mutex_lock(&dpm_list_mtx);
        while(!list_empty(&dpm_off)) {
                struct list_head * entry = dpm_off.next;
                struct device * dev = to_device(entry);
@@ -88,13 +80,12 @@ void dpm_resume(void)
                get_device(dev);
                list_move_tail(entry, &dpm_active);
 
-               up(&dpm_list_sem);
-               if (!dev->power.prev_state.event)
-                       resume_device(dev);
-               down(&dpm_list_sem);
+               mutex_unlock(&dpm_list_mtx);
+               resume_device(dev);
+               mutex_lock(&dpm_list_mtx);
                put_device(dev);
        }
-       up(&dpm_list_sem);
+       mutex_unlock(&dpm_list_mtx);
 }
 
 
@@ -108,9 +99,9 @@ void dpm_resume(void)
 void device_resume(void)
 {
        might_sleep();
-       down(&dpm_sem);
+       mutex_lock(&dpm_mtx);
        dpm_resume();
-       up(&dpm_sem);
+       mutex_unlock(&dpm_mtx);
 }
 
 EXPORT_SYMBOL_GPL(device_resume);
index 96370ec1d673fc3d07a2a03b496980517891c304..df6174d858664288dc93fb34c36c23bfe8faed29 100644 (file)
@@ -32,9 +32,9 @@ static void runtime_resume(struct device * dev)
 
 void dpm_runtime_resume(struct device * dev)
 {
-       down(&dpm_sem);
+       mutex_lock(&dpm_mtx);
        runtime_resume(dev);
-       up(&dpm_sem);
+       mutex_unlock(&dpm_mtx);
 }
 EXPORT_SYMBOL(dpm_runtime_resume);
 
@@ -49,7 +49,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
 {
        int error = 0;
 
-       down(&dpm_sem);
+       mutex_lock(&dpm_mtx);
        if (dev->power.power_state.event == state.event)
                goto Done;
 
@@ -59,7 +59,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
        if (!(error = suspend_device(dev, state)))
                dev->power.power_state = state;
  Done:
-       up(&dpm_sem);
+       mutex_unlock(&dpm_mtx);
        return error;
 }
 EXPORT_SYMBOL(dpm_runtime_suspend);
@@ -78,8 +78,8 @@ EXPORT_SYMBOL(dpm_runtime_suspend);
  */
 void dpm_set_power_state(struct device * dev, pm_message_t state)
 {
-       down(&dpm_sem);
+       mutex_lock(&dpm_mtx);
        dev->power.power_state = state;
-       up(&dpm_sem);
+       mutex_unlock(&dpm_mtx);
 }
 #endif  /*  0  */
index 42d2b86ba7652944917a2b40a31d70e485a60622..26df9b231737de51c0541567553704cac4381d70 100644 (file)
@@ -40,6 +40,14 @@ static inline char *suspend_verb(u32 event)
 }
 
 
+static void
+suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
+{
+       dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
+               ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
+               ", may wakeup" : "");
+}
+
 /**
  *     suspend_device - Save state of one device.
  *     @dev:   Device.
@@ -55,49 +63,21 @@ int suspend_device(struct device * dev, pm_message_t state)
                dev_dbg(dev, "PM: suspend %d-->%d\n",
                        dev->power.power_state.event, state.event);
        }
-       if (dev->power.pm_parent
-                       && dev->power.pm_parent->power.power_state.event) {
-               dev_err(dev,
-                       "PM: suspend %d->%d, parent %s already %d\n",
-                       dev->power.power_state.event, state.event,
-                       dev->power.pm_parent->bus_id,
-                       dev->power.pm_parent->power.power_state.event);
-       }
-
-       dev->power.prev_state = dev->power.power_state;
 
-       if (dev->class && dev->class->suspend && !dev->power.power_state.event) {
-               dev_dbg(dev, "class %s%s\n",
-                       suspend_verb(state.event),
-                       ((state.event == PM_EVENT_SUSPEND)
-                                       && device_may_wakeup(dev))
-                               ? ", may wakeup"
-                               : ""
-                       );
+       if (dev->class && dev->class->suspend) {
+               suspend_device_dbg(dev, state, "class ");
                error = dev->class->suspend(dev, state);
                suspend_report_result(dev->class->suspend, error);
        }
 
-       if (!error && dev->type && dev->type->suspend && !dev->power.power_state.event) {
-               dev_dbg(dev, "%s%s\n",
-                       suspend_verb(state.event),
-                       ((state.event == PM_EVENT_SUSPEND)
-                                       && device_may_wakeup(dev))
-                               ? ", may wakeup"
-                               : ""
-                       );
+       if (!error && dev->type && dev->type->suspend) {
+               suspend_device_dbg(dev, state, "type ");
                error = dev->type->suspend(dev, state);
                suspend_report_result(dev->type->suspend, error);
        }
 
-       if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
-               dev_dbg(dev, "%s%s\n",
-                       suspend_verb(state.event),
-                       ((state.event == PM_EVENT_SUSPEND)
-                                       && device_may_wakeup(dev))
-                               ? ", may wakeup"
-                               : ""
-                       );
+       if (!error && dev->bus && dev->bus->suspend) {
+               suspend_device_dbg(dev, state, "");
                error = dev->bus->suspend(dev, state);
                suspend_report_result(dev->bus->suspend, error);
        }
@@ -108,21 +88,15 @@ int suspend_device(struct device * dev, pm_message_t state)
 
 /*
  * This is called with interrupts off, only a single CPU
- * running. We can't do down() on a semaphore (and we don't
+ * running. We can't acquire a mutex or semaphore (and we don't
  * need the protection)
  */
 static int suspend_device_late(struct device *dev, pm_message_t state)
 {
        int error = 0;
 
-       if (dev->bus && dev->bus->suspend_late && !dev->power.power_state.event) {
-               dev_dbg(dev, "LATE %s%s\n",
-                       suspend_verb(state.event),
-                       ((state.event == PM_EVENT_SUSPEND)
-                                       && device_may_wakeup(dev))
-                               ? ", may wakeup"
-                               : ""
-                       );
+       if (dev->bus && dev->bus->suspend_late) {
+               suspend_device_dbg(dev, state, "LATE ");
                error = dev->bus->suspend_late(dev, state);
                suspend_report_result(dev->bus->suspend_late, error);
        }
@@ -153,18 +127,18 @@ int device_suspend(pm_message_t state)
        int error = 0;
 
        might_sleep();
-       down(&dpm_sem);
-       down(&dpm_list_sem);
+       mutex_lock(&dpm_mtx);
+       mutex_lock(&dpm_list_mtx);
        while (!list_empty(&dpm_active) && error == 0) {
                struct list_head * entry = dpm_active.prev;
                struct device * dev = to_device(entry);
 
                get_device(dev);
-               up(&dpm_list_sem);
+               mutex_unlock(&dpm_list_mtx);
 
                error = suspend_device(dev, state);
 
-               down(&dpm_list_sem);
+               mutex_lock(&dpm_list_mtx);
 
                /* Check if the device got removed */
                if (!list_empty(&dev->power.entry)) {
@@ -179,11 +153,11 @@ int device_suspend(pm_message_t state)
                                error == -EAGAIN ? " (please convert to suspend_late)" : "");
                put_device(dev);
        }
-       up(&dpm_list_sem);
+       mutex_unlock(&dpm_list_mtx);
        if (error)
                dpm_resume();
 
-       up(&dpm_sem);
+       mutex_unlock(&dpm_mtx);
        return error;
 }
 
index 29f1291966c17a55d8f063eeabbd715b647a1254..18febe26caa1c3640fc9d4df27e6a66775b4665f 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/string.h>
 #include <linux/pm.h>
 #include <linux/device.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 #include "base.h"
 
@@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(sysdev_class_unregister);
 
 
 static LIST_HEAD(sysdev_drivers);
-static DECLARE_MUTEX(sysdev_drivers_lock);
+static DEFINE_MUTEX(sysdev_drivers_lock);
 
 /**
  *     sysdev_driver_register - Register auxillary driver
@@ -172,7 +172,7 @@ static DECLARE_MUTEX(sysdev_drivers_lock);
 int sysdev_driver_register(struct sysdev_class * cls,
                           struct sysdev_driver * drv)
 {
-       down(&sysdev_drivers_lock);
+       mutex_lock(&sysdev_drivers_lock);
        if (cls && kset_get(&cls->kset)) {
                list_add_tail(&drv->entry, &cls->drivers);
 
@@ -184,7 +184,7 @@ int sysdev_driver_register(struct sysdev_class * cls,
                }
        } else
                list_add_tail(&drv->entry, &sysdev_drivers);
-       up(&sysdev_drivers_lock);
+       mutex_unlock(&sysdev_drivers_lock);
        return 0;
 }
 
@@ -197,7 +197,7 @@ int sysdev_driver_register(struct sysdev_class * cls,
 void sysdev_driver_unregister(struct sysdev_class * cls,
                              struct sysdev_driver * drv)
 {
-       down(&sysdev_drivers_lock);
+       mutex_lock(&sysdev_drivers_lock);
        list_del_init(&drv->entry);
        if (cls) {
                if (drv->remove) {
@@ -207,7 +207,7 @@ void sysdev_driver_unregister(struct sysdev_class * cls,
                }
                kset_put(&cls->kset);
        }
-       up(&sysdev_drivers_lock);
+       mutex_unlock(&sysdev_drivers_lock);
 }
 
 EXPORT_SYMBOL_GPL(sysdev_driver_register);
@@ -246,7 +246,7 @@ int sysdev_register(struct sys_device * sysdev)
        if (!error) {
                struct sysdev_driver * drv;
 
-               down(&sysdev_drivers_lock);
+               mutex_lock(&sysdev_drivers_lock);
                /* Generic notification is implicit, because it's that
                 * code that should have called us.
                 */
@@ -262,7 +262,7 @@ int sysdev_register(struct sys_device * sysdev)
                        if (drv->add)
                                drv->add(sysdev);
                }
-               up(&sysdev_drivers_lock);
+               mutex_unlock(&sysdev_drivers_lock);
        }
        return error;
 }
@@ -271,7 +271,7 @@ void sysdev_unregister(struct sys_device * sysdev)
 {
        struct sysdev_driver * drv;
 
-       down(&sysdev_drivers_lock);
+       mutex_lock(&sysdev_drivers_lock);
        list_for_each_entry(drv, &sysdev_drivers, entry) {
                if (drv->remove)
                        drv->remove(sysdev);
@@ -281,7 +281,7 @@ void sysdev_unregister(struct sys_device * sysdev)
                if (drv->remove)
                        drv->remove(sysdev);
        }
-       up(&sysdev_drivers_lock);
+       mutex_unlock(&sysdev_drivers_lock);
 
        kobject_unregister(&sysdev->kobj);
 }
@@ -308,7 +308,7 @@ void sysdev_shutdown(void)
 
        pr_debug("Shutting Down System Devices\n");
 
-       down(&sysdev_drivers_lock);
+       mutex_lock(&sysdev_drivers_lock);
        list_for_each_entry_reverse(cls, &system_subsys.list,
                                    kset.kobj.entry) {
                struct sys_device * sysdev;
@@ -337,7 +337,7 @@ void sysdev_shutdown(void)
                                cls->shutdown(sysdev);
                }
        }
-       up(&sysdev_drivers_lock);
+       mutex_unlock(&sysdev_drivers_lock);
 }
 
 static void __sysdev_resume(struct sys_device *dev)
index f1b9dd7d47d62c00868acdba0927d68a0c8777e0..ce64e86d6ffbb9d4205a96f0e189dec7519632ca 100644 (file)
@@ -146,8 +146,7 @@ static void pkt_kobj_release(struct kobject *kobj)
  **********************************************************/
 
 #define DEF_ATTR(_obj,_name,_mode) \
-       static struct attribute _obj = { \
-               .name = _name, .owner = THIS_MODULE, .mode = _mode }
+       static struct attribute _obj = { .name = _name, .mode = _mode }
 
 /**********************************************************
   /sys/class/pktcdvd/pktcdvd[0-7]/
index 746a118a9b52ba1792b28861605902534290d1d4..18c8b6c0db20239ae3095c2547a13cbab66dff5c 100644 (file)
@@ -1547,10 +1547,8 @@ static void ub_reset_enter(struct ub_dev *sc, int try)
 #endif
 
 #if 0 /* We let them stop themselves. */
-       struct list_head *p;
        struct ub_lun *lun;
-       list_for_each(p, &sc->luns) {
-               lun = list_entry(p, struct ub_lun, link);
+       list_for_each_entry(lun, &sc->luns, link) {
                blk_stop_queue(lun->disk->queue);
        }
 #endif
@@ -1562,7 +1560,6 @@ static void ub_reset_task(struct work_struct *work)
 {
        struct ub_dev *sc = container_of(work, struct ub_dev, reset_work);
        unsigned long flags;
-       struct list_head *p;
        struct ub_lun *lun;
        int lkr, rc;
 
@@ -1608,8 +1605,7 @@ static void ub_reset_task(struct work_struct *work)
        spin_lock_irqsave(sc->lock, flags);
        sc->reset = 0;
        tasklet_schedule(&sc->tasklet);
-       list_for_each(p, &sc->luns) {
-               lun = list_entry(p, struct ub_lun, link);
+       list_for_each_entry(lun, &sc->luns, link) {
                blk_start_queue(lun->disk->queue);
        }
        wake_up(&sc->reset_wait);
@@ -2348,7 +2344,6 @@ err_alloc:
 static void ub_disconnect(struct usb_interface *intf)
 {
        struct ub_dev *sc = usb_get_intfdata(intf);
-       struct list_head *p;
        struct ub_lun *lun;
        unsigned long flags;
 
@@ -2403,8 +2398,7 @@ static void ub_disconnect(struct usb_interface *intf)
        /*
         * Unregister the upper layer.
         */
-       list_for_each (p, &sc->luns) {
-               lun = list_entry(p, struct ub_lun, link);
+       list_for_each_entry(lun, &sc->luns, link) {
                del_gendisk(lun->disk);
                /*
                 * I wish I could do:
index ef683ebd367caf7b4b4045857525301ef2e25285..f6648682b43ab4669a8e06dbb46adf9649c94049 100644 (file)
@@ -374,20 +374,6 @@ config ISTALLION
          To compile this driver as a module, choose M here: the
          module will be called istallion.
 
-config AU1000_UART
-       bool "Enable Au1000 UART Support"
-       depends on SERIAL_NONSTANDARD && MIPS
-       help
-         If you have an Alchemy AU1000 processor (MIPS based) and you want
-         to use serial ports, say Y.  Otherwise, say N.
-
-config AU1000_SERIAL_CONSOLE
-       bool "Enable Au1000 serial console"
-       depends on AU1000_UART
-       help
-         If you have an Alchemy AU1000 processor (MIPS based) and you want
-         to use a console on a serial port, say Y.  Otherwise, say N.
-
 config SERIAL_DEC
        bool "DECstation serial support"
        depends on MACH_DECSTATION
@@ -815,7 +801,7 @@ config SGI_IP27_RTC
 
 config GEN_RTC
        tristate "Generic /dev/rtc emulation"
-       depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV && !S390 && !SUPERH
+       depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH
        ---help---
          If you say Y here and create a character special file /dev/rtc with
          major number 10 and minor number 135 using mknod ("man mknod"), you
index e6c534e6284638a610d8a1549b52530d6d4225af..df0ddf14b85cd3d695718beffae359b4581881f8 100644 (file)
@@ -462,9 +462,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
         * erratum 46: Setup violation on AGP SBA pins - Disable side band addressing.
         * With this lot disabled, we should prevent lockups. */
        if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_700E) {
-               u8 revision=0;
-               pci_read_config_byte(pdev, PCI_REVISION_ID, &revision);
-               if (revision == 0x10 || revision == 0x11) {
+               if (pdev->revision == 0x10 || pdev->revision == 0x11) {
                        agp_bridge->flags = AGP_ERRATA_FASTWRITES;
                        agp_bridge->flags |= AGP_ERRATA_SBA;
                        agp_bridge->flags |= AGP_ERRATA_1X;
index 801abdd290669a092765191ef86450593dc23c2d..d95662e96326dfe152029b2042890f24ccfa5148 100644 (file)
@@ -367,10 +367,8 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
 static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge)
 {
        char *revstring;
-       u8 rev_id;
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-       switch (rev_id) {
+       switch (pdev->revision) {
        case 0x01: revstring="A0"; break;
        case 0x02: revstring="A1"; break;
        case 0x11: revstring="B0"; break;
@@ -386,7 +384,7 @@ static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data
         * Work around errata.
         * Chips before B2 stepping incorrectly reporting v3.5
         */
-       if (rev_id < 0x13) {
+       if (pdev->revision < 0x13) {
                printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n");
                bridge->major_version = 3;
                bridge->minor_version = 0;
index ebdd6dd66edb6b27931061a3ea732014f58bb31e..1b47c89a1b992c7946b3d9b6ae1fcf843a47eebb 100644 (file)
@@ -321,7 +321,7 @@ EXPORT_SYMBOL(agp_try_unsupported_boot);
 static int __init agp_init(void)
 {
        if (!agp_off)
-               printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n",
+               printk(KERN_INFO "Linux agpgart interface v%d.%d\n",
                        AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
        return 0;
 }
index 8e222f2b80cc4bb2ee28535e936fcd83d6fb397c..b5df7e61aeb2aa4b7282733d357a24dee06b887a 100644 (file)
@@ -2171,52 +2171,42 @@ static int create_files(struct bmc_device *bmc)
        int err;
 
        bmc->device_id_attr.attr.name = "device_id";
-       bmc->device_id_attr.attr.owner = THIS_MODULE;
        bmc->device_id_attr.attr.mode = S_IRUGO;
        bmc->device_id_attr.show = device_id_show;
 
        bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs";
-       bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE;
        bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO;
        bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show;
 
        bmc->revision_attr.attr.name = "revision";
-       bmc->revision_attr.attr.owner = THIS_MODULE;
        bmc->revision_attr.attr.mode = S_IRUGO;
        bmc->revision_attr.show = revision_show;
 
        bmc->firmware_rev_attr.attr.name = "firmware_revision";
-       bmc->firmware_rev_attr.attr.owner = THIS_MODULE;
        bmc->firmware_rev_attr.attr.mode = S_IRUGO;
        bmc->firmware_rev_attr.show = firmware_rev_show;
 
        bmc->version_attr.attr.name = "ipmi_version";
-       bmc->version_attr.attr.owner = THIS_MODULE;
        bmc->version_attr.attr.mode = S_IRUGO;
        bmc->version_attr.show = ipmi_version_show;
 
        bmc->add_dev_support_attr.attr.name = "additional_device_support";
-       bmc->add_dev_support_attr.attr.owner = THIS_MODULE;
        bmc->add_dev_support_attr.attr.mode = S_IRUGO;
        bmc->add_dev_support_attr.show = add_dev_support_show;
 
        bmc->manufacturer_id_attr.attr.name = "manufacturer_id";
-       bmc->manufacturer_id_attr.attr.owner = THIS_MODULE;
        bmc->manufacturer_id_attr.attr.mode = S_IRUGO;
        bmc->manufacturer_id_attr.show = manufacturer_id_show;
 
        bmc->product_id_attr.attr.name = "product_id";
-       bmc->product_id_attr.attr.owner = THIS_MODULE;
        bmc->product_id_attr.attr.mode = S_IRUGO;
        bmc->product_id_attr.show = product_id_show;
 
        bmc->guid_attr.attr.name = "guid";
-       bmc->guid_attr.attr.owner = THIS_MODULE;
        bmc->guid_attr.attr.mode = S_IRUGO;
        bmc->guid_attr.show = guid_show;
 
        bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision";
-       bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE;
        bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO;
        bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show;
 
index 0cea8d4907dfb965d509e356f51c18ca23118756..e5ed09192be8675b615f6978dcf92f41a3dcf316 100644 (file)
  *  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/platform_device.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/init.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
-#include <asm/cpu.h>
 #include <asm/io.h>
 #include <asm/vr41xx/giu.h>
 #include <asm/vr41xx/irq.h>
@@ -44,18 +43,6 @@ static int major;    /* default is dynamic major device number */
 module_param(major, int, 0);
 MODULE_PARM_DESC(major, "Major device number");
 
-#define GIU_TYPE1_START                0x0b000100UL
-#define GIU_TYPE1_SIZE         0x20UL
-
-#define GIU_TYPE2_START                0x0f000140UL
-#define GIU_TYPE2_SIZE         0x20UL
-
-#define GIU_TYPE3_START                0x0f000140UL
-#define GIU_TYPE3_SIZE         0x28UL
-
-#define GIU_PULLUPDOWN_START   0x0b0002e0UL
-#define GIU_PULLUPDOWN_SIZE    0x04UL
-
 #define GIUIOSELL      0x00
 #define GIUIOSELH      0x02
 #define GIUPIODL       0x04
@@ -89,8 +76,6 @@ MODULE_PARM_DESC(major, "Major device number");
 #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
 
 static spinlock_t giu_lock;
-static struct resource *giu_resource1;
-static struct resource *giu_resource2;
 static unsigned long giu_flags;
 static unsigned int giu_nr_pins;
 
@@ -234,7 +219,7 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
                                giu_set(GIUINTHTSELL, mask);
                        else
                                giu_clear(GIUINTHTSELL, mask);
-                       if (current_cpu_data.cputype == CPU_VR4133) {
+                       if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
                                switch (trigger) {
                                case IRQ_TRIGGER_EDGE_FALLING:
                                        giu_set(GIUFEDGEINHL, mask);
@@ -269,7 +254,7 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
                                giu_set(GIUINTHTSELH, mask);
                        else
                                giu_clear(GIUINTHTSELH, mask);
-                       if (current_cpu_data.cputype == CPU_VR4133) {
+                       if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
                                switch (trigger) {
                                case IRQ_TRIGGER_EDGE_FALLING:
                                        giu_set(GIUFEDGEINHH, mask);
@@ -298,7 +283,6 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
                giu_write(GIUINTSTATH, mask);
        }
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
 
 void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
@@ -321,7 +305,6 @@ void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
                giu_write(GIUINTSTATH, mask);
        }
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
 
 gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
@@ -350,7 +333,6 @@ gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
 
        return GPIO_DATA_LOW;
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
 
 int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
@@ -388,7 +370,6 @@ int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
 
        return 0;
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
 
 int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
@@ -438,7 +419,6 @@ int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
 
        return 0;
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
 
 int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
@@ -477,7 +457,6 @@ int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
 
        return 0;
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
 
 static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
@@ -596,61 +575,40 @@ static const struct file_operations gpio_fops = {
 
 static int __devinit giu_probe(struct platform_device *dev)
 {
-       unsigned long start, size, flags = 0;
-       unsigned int nr_pins = 0, trigger, i, pin;
-       struct resource *res1, *res2 = NULL;
-       void *base;
+       struct resource *res;
+       unsigned int trigger, i, pin;
        struct irq_chip *chip;
-       int retval;
-
-       switch (current_cpu_data.cputype) {
-       case CPU_VR4111:
-       case CPU_VR4121:
-               start = GIU_TYPE1_START;
-               size = GIU_TYPE1_SIZE;
-               flags = GPIO_HAS_PULLUPDOWN_IO;
-               nr_pins = 50;
+       int irq, retval;
+
+       switch (dev->id) {
+       case GPIO_50PINS_PULLUPDOWN:
+               giu_flags = GPIO_HAS_PULLUPDOWN_IO;
+               giu_nr_pins = 50;
                break;
-       case CPU_VR4122:
-       case CPU_VR4131:
-               start = GIU_TYPE2_START;
-               size = GIU_TYPE2_SIZE;
-               nr_pins = 36;
+       case GPIO_36PINS:
+               giu_nr_pins = 36;
                break;
-       case CPU_VR4133:
-               start = GIU_TYPE3_START;
-               size = GIU_TYPE3_SIZE;
-               flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
-               nr_pins = 48;
+       case GPIO_48PINS_EDGE_SELECT:
+               giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
+               giu_nr_pins = 48;
                break;
        default:
+               printk(KERN_ERR "GIU: unknown ID %d\n", dev->id);
                return -ENODEV;
        }
 
-       res1 = request_mem_region(start, size, "GIU");
-       if (res1 == NULL)
+       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (!res)
                return -EBUSY;
 
-       base = ioremap(start, size);
-       if (base == NULL) {
-               release_resource(res1);
+       giu_base = ioremap(res->start, res->end - res->start + 1);
+       if (!giu_base)
                return -ENOMEM;
-       }
-
-       if (flags & GPIO_HAS_PULLUPDOWN_IO) {
-               res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU");
-               if (res2 == NULL) {
-                       iounmap(base);
-                       release_resource(res1);
-                       return -EBUSY;
-               }
-       }
 
        retval = register_chrdev(major, "GIU", &gpio_fops);
        if (retval < 0) {
-               iounmap(base);
-               release_resource(res1);
-               release_resource(res2);
+               iounmap(giu_base);
+               giu_base = NULL;
                return retval;
        }
 
@@ -660,11 +618,6 @@ static int __devinit giu_probe(struct platform_device *dev)
        }
 
        spin_lock_init(&giu_lock);
-       giu_base = base;
-       giu_resource1 = res1;
-       giu_resource2 = res2;
-       giu_flags = flags;
-       giu_nr_pins = nr_pins;
 
        giu_write(GIUINTENL, 0);
        giu_write(GIUINTENH, 0);
@@ -685,22 +638,23 @@ static int __devinit giu_probe(struct platform_device *dev)
 
        }
 
-       return cascade_irq(GIUINT_IRQ, giu_get_irq);
+       irq = platform_get_irq(dev, 0);
+       if (irq < 0 || irq >= NR_IRQS)
+               return -EBUSY;
+
+       return cascade_irq(irq, giu_get_irq);
 }
 
 static int __devexit giu_remove(struct platform_device *dev)
 {
-       iounmap(giu_base);
-
-       release_resource(giu_resource1);
-       if (giu_flags & GPIO_HAS_PULLUPDOWN_IO)
-               release_resource(giu_resource2);
+       if (giu_base) {
+               iounmap(giu_base);
+               giu_base = NULL;
+       }
 
        return 0;
 }
 
-static struct platform_device *giu_platform_device;
-
 static struct platform_driver giu_device_driver = {
        .probe          = giu_probe,
        .remove         = __devexit_p(giu_remove),
@@ -712,30 +666,12 @@ static struct platform_driver giu_device_driver = {
 
 static int __init vr41xx_giu_init(void)
 {
-       int retval;
-
-       giu_platform_device = platform_device_alloc("GIU", -1);
-       if (!giu_platform_device)
-               return -ENOMEM;
-
-       retval = platform_device_add(giu_platform_device);
-       if (retval < 0) {
-               platform_device_put(giu_platform_device);
-               return retval;
-       }
-
-       retval = platform_driver_register(&giu_device_driver);
-       if (retval < 0)
-               platform_device_unregister(giu_platform_device);
-
-       return retval;
+       return platform_driver_register(&giu_device_driver);
 }
 
 static void __exit vr41xx_giu_exit(void)
 {
        platform_driver_unregister(&giu_device_driver);
-
-       platform_device_unregister(giu_platform_device);
 }
 
 module_init(vr41xx_giu_init);
index 5cfcff532545b019e3f984dbf3de5273b91d464b..e783dbf0f162fe736339366b6afea4af55ea6cc0 100644 (file)
@@ -105,14 +105,11 @@ static inline void acpi_pm_need_workaround(void)
  */
 static void __devinit acpi_pm_check_blacklist(struct pci_dev *dev)
 {
-       u8 rev;
-
        if (acpi_pm_good)
                return;
 
-       pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
        /* the bug has been fixed in PIIX4M */
-       if (rev < 3) {
+       if (dev->revision < 3) {
                printk(KERN_WARNING "* Found PM-Timer Bug on the chipset."
                       " Due to workarounds for a bug,\n"
                       "* this clock source is slow. Consider trying"
index eb37fba9b7efccf163badc70450aee38873b60d3..2f6a73c01b718318d583123f66aaa6c622dca6a0 100644 (file)
  */
 static struct cpufreq_driver *cpufreq_driver;
 static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
+#ifdef CONFIG_HOTPLUG_CPU
+/* This one keeps track of the previously set governor of a removed CPU */
+static struct cpufreq_governor *cpufreq_cpu_governor[NR_CPUS];
+#endif
 static DEFINE_SPINLOCK(cpufreq_driver_lock);
 
 /*
@@ -770,9 +774,17 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
        }
        policy->user_policy.min = policy->cpuinfo.min_freq;
        policy->user_policy.max = policy->cpuinfo.max_freq;
-       policy->user_policy.governor = policy->governor;
 
 #ifdef CONFIG_SMP
+
+#ifdef CONFIG_HOTPLUG_CPU
+       if (cpufreq_cpu_governor[cpu]){
+               policy->governor = cpufreq_cpu_governor[cpu];
+               dprintk("Restoring governor %s for cpu %d\n",
+                      policy->governor->name, cpu);
+       }
+#endif
+
        for_each_cpu_mask(j, policy->cpus) {
                if (cpu == j)
                        continue;
@@ -826,13 +838,21 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
        /* set up files for this cpu device */
        drv_attr = cpufreq_driver->attr;
        while ((drv_attr) && (*drv_attr)) {
-               sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+               ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+               if (ret)
+                       goto err_out_driver_exit;
                drv_attr++;
        }
-       if (cpufreq_driver->get)
-               sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
-       if (cpufreq_driver->target)
-               sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+       if (cpufreq_driver->get){
+               ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
+               if (ret)
+                       goto err_out_driver_exit;
+       }
+       if (cpufreq_driver->target){
+               ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+               if (ret)
+                       goto err_out_driver_exit;
+       }
 
        spin_lock_irqsave(&cpufreq_driver_lock, flags);
        for_each_cpu_mask(j, policy->cpus) {
@@ -865,6 +885,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
        /* set default policy */
        ret = __cpufreq_set_policy(policy, &new_policy);
        policy->user_policy.policy = policy->policy;
+       policy->user_policy.governor = policy->governor;
 
        unlock_policy_rwsem_write(cpu);
 
@@ -961,6 +982,11 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
        }
 
 #ifdef CONFIG_SMP
+
+#ifdef CONFIG_HOTPLUG_CPU
+       cpufreq_cpu_governor[cpu] = data->governor;
+#endif
+
        /* if we have other CPUs still registered, we need to unlink them,
         * or else wait_for_completion below will lock up. Clean the
         * cpufreq_cpu_data[] while holding the lock, and remove the sysfs
@@ -981,6 +1007,9 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
                        if (j == cpu)
                                continue;
                        dprintk("removing link for cpu %u\n", j);
+#ifdef CONFIG_HOTPLUG_CPU
+                       cpufreq_cpu_governor[j] = data->governor;
+#endif
                        cpu_sys_dev = get_cpu_sysdev(j);
                        sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
                        cpufreq_cpu_put(data);
@@ -1679,7 +1708,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
 {
        unsigned int cpu = (unsigned long)hcpu;
        struct sys_device *sys_dev;
-       struct cpufreq_policy *policy;
 
        sys_dev = get_cpu_sysdev(cpu);
        if (sys_dev) {
@@ -1693,11 +1721,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
                        if (unlikely(lock_policy_rwsem_write(cpu)))
                                BUG();
 
-                       policy = cpufreq_cpu_data[cpu];
-                       if (policy) {
-                               __cpufreq_driver_target(policy, policy->min,
-                                               CPUFREQ_RELATION_H);
-                       }
                        __cpufreq_remove_dev(sys_dev);
                        break;
                case CPU_DOWN_FAILED:
index 8532bb79e5fc52dfc8d45ac3aba16b3f6ecd796f..e794527e49251d10564e703805b1965844c12b65 100644 (file)
@@ -96,15 +96,25 @@ static struct dbs_tuners {
 
 static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
 {
-       cputime64_t retval;
+       cputime64_t idle_time;
+       cputime64_t cur_jiffies;
+       cputime64_t busy_time;
 
-       retval = cputime64_add(kstat_cpu(cpu).cpustat.idle,
-                       kstat_cpu(cpu).cpustat.iowait);
+       cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
+       busy_time = cputime64_add(kstat_cpu(cpu).cpustat.user,
+                       kstat_cpu(cpu).cpustat.system);
 
-       if (dbs_tuners_ins.ignore_nice)
-               retval = cputime64_add(retval, kstat_cpu(cpu).cpustat.nice);
+       busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.irq);
+       busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.softirq);
+       busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.steal);
 
-       return retval;
+       if (!dbs_tuners_ins.ignore_nice) {
+               busy_time = cputime64_add(busy_time,
+                               kstat_cpu(cpu).cpustat.nice);
+       }
+
+       idle_time = cputime64_sub(cur_jiffies, busy_time);
+       return idle_time;
 }
 
 /*
@@ -325,7 +335,7 @@ static struct attribute_group dbs_attr_group = {
 static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
 {
        unsigned int idle_ticks, total_ticks;
-       unsigned int load;
+       unsigned int load = 0;
        cputime64_t cur_jiffies;
 
        struct cpufreq_policy *policy;
@@ -339,7 +349,8 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
        cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
        total_ticks = (unsigned int) cputime64_sub(cur_jiffies,
                        this_dbs_info->prev_cpu_wall);
-       this_dbs_info->prev_cpu_wall = cur_jiffies;
+       this_dbs_info->prev_cpu_wall = get_jiffies_64();
+
        if (!total_ticks)
                return;
        /*
@@ -370,7 +381,8 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
                if (tmp_idle_ticks < idle_ticks)
                        idle_ticks = tmp_idle_ticks;
        }
-       load = (100 * (total_ticks - idle_ticks)) / total_ticks;
+       if (likely(total_ticks > idle_ticks))
+               load = (100 * (total_ticks - idle_ticks)) / total_ticks;
 
        /* Check for frequency increase */
        if (load > dbs_tuners_ins.up_threshold) {
index d2f0cbd8b8f3f294ef7a1f834d52bbfcb2bf02c3..917b9bab9ccbc924a6e583997cf96dc03e09071f 100644 (file)
@@ -25,8 +25,7 @@ static spinlock_t cpufreq_stats_lock;
 
 #define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \
 static struct freq_attr _attr_##_name = {\
-       .attr = {.name = __stringify(_name), .owner = THIS_MODULE, \
-               .mode = _mode, }, \
+       .attr = {.name = __stringify(_name), .mode = _mode, }, \
        .show = _show,\
 };
 
index 860345c7799ab1188c21945756ec6e696019b10e..51bedab6c808da57dd2b26e896021613d2540655 100644 (file)
@@ -37,6 +37,7 @@ static unsigned int   cpu_set_freq[NR_CPUS]; /* CPU freq desired by userspace */
 static unsigned int    cpu_is_managed[NR_CPUS];
 
 static DEFINE_MUTEX    (userspace_mutex);
+static int cpus_using_userspace_governor;
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
 
@@ -47,7 +48,11 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
 {
         struct cpufreq_freqs *freq = data;
 
-       dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n", freq->cpu, freq->new);
+       if (!cpu_is_managed[freq->cpu])
+               return 0;
+
+       dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n",
+                       freq->cpu, freq->new);
        cpu_cur_freq[freq->cpu] = freq->new;
 
         return 0;
@@ -120,7 +125,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
 
 static struct freq_attr freq_attr_scaling_setspeed =
 {
-       .attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE },
+       .attr = { .name = "scaling_setspeed", .mode = 0644 },
        .show = show_speed,
        .store = store_speed,
 };
@@ -142,6 +147,13 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
                if (rc)
                        goto start_out;
 
+               if (cpus_using_userspace_governor == 0) {
+                       cpufreq_register_notifier(
+                                       &userspace_cpufreq_notifier_block,
+                                       CPUFREQ_TRANSITION_NOTIFIER);
+               }
+               cpus_using_userspace_governor++;
+
                cpu_is_managed[cpu] = 1;
                cpu_min_freq[cpu] = policy->min;
                cpu_max_freq[cpu] = policy->max;
@@ -153,6 +165,13 @@ start_out:
                break;
        case CPUFREQ_GOV_STOP:
                mutex_lock(&userspace_mutex);
+               cpus_using_userspace_governor--;
+               if (cpus_using_userspace_governor == 0) {
+                       cpufreq_unregister_notifier(
+                                       &userspace_cpufreq_notifier_block,
+                                       CPUFREQ_TRANSITION_NOTIFIER);
+               }
+
                cpu_is_managed[cpu] = 0;
                cpu_min_freq[cpu] = 0;
                cpu_max_freq[cpu] = 0;
@@ -198,7 +217,6 @@ EXPORT_SYMBOL(cpufreq_gov_userspace);
 
 static int __init cpufreq_gov_userspace_init(void)
 {
-       cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
        return cpufreq_register_governor(&cpufreq_gov_userspace);
 }
 
@@ -206,7 +224,6 @@ static int __init cpufreq_gov_userspace_init(void)
 static void __exit cpufreq_gov_userspace_exit(void)
 {
        cpufreq_unregister_governor(&cpufreq_gov_userspace);
-        cpufreq_unregister_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
 }
 
 
index e7490925fdcf51acaf7d00039a609465a1aaf54d..5409f3afb3f85fab2a0b7e160c2972805b0a374d 100644 (file)
@@ -199,7 +199,6 @@ static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
 struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
        .attr = { .name = "scaling_available_frequencies",
                  .mode = 0444,
-                 .owner=THIS_MODULE
                },
        .show = show_available_freqs,
 };
index 72be6c63edfc01767d503eaa57ba9c40e0219498..b31756d599787b6872077f1829c506574a8f6a24 100644 (file)
@@ -8,8 +8,8 @@ menu "DMA Engine support"
 config DMA_ENGINE
        bool "Support for DMA engines"
        ---help---
-         DMA engines offload copy operations from the CPU to dedicated
-         hardware, allowing the copies to happen asynchronously.
+          DMA engines offload bulk memory operations from the CPU to dedicated
+          hardware, allowing the operations to happen asynchronously.
 
 comment "DMA Clients"
 
@@ -32,4 +32,12 @@ config INTEL_IOATDMA
        ---help---
          Enable support for the Intel(R) I/OAT DMA engine.
 
+config INTEL_IOP_ADMA
+        tristate "Intel IOP ADMA support"
+        depends on DMA_ENGINE && (ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX)
+       select ASYNC_CORE
+        default m
+        ---help---
+          Enable support for the Intel(R) IOP Series RAID engines.
+
 endmenu
index bdcfdbdb1aeceb7a753cf98f12aa7a5f6d4ebeef..b3839b687ae033841f04baa7193ec3c24dd2b05b 100644 (file)
@@ -1,3 +1,4 @@
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
 obj-$(CONFIG_NET_DMA) += iovlock.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
+obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
index 322ee2984e3d0108302764832fabce469dfaeb4c..82489923af09a6ae048a50c1bf471e43f9260492 100644 (file)
  * Each device has a channels list, which runs unlocked but is never modified
  * once the device is registered, it's just setup by the driver.
  *
- * Each client has a channels list, it's only modified under the client->lock
- * and in an RCU callback, so it's safe to read under rcu_read_lock().
+ * Each client is responsible for keeping track of the channels it uses.  See
+ * the definition of dma_event_callback in dmaengine.h.
  *
  * Each device has a kref, which is initialized to 1 when the device is
- * registered. A kref_put is done for each class_device registered.  When the
+ * registered. A kref_get is done for each class_device registered.  When the
  * class_device is released, the coresponding kref_put is done in the release
  * method. Every time one of the device's channels is allocated to a client,
  * a kref_get occurs.  When the channel is freed, the coresponding kref_put
  * references to finish.
  *
  * Each channel has an open-coded implementation of Rusty Russell's "bigref,"
- * with a kref and a per_cpu local_t.  A single reference is set when on an
- * ADDED event, and removed with a REMOVE event.  Net DMA client takes an
- * extra reference per outstanding transaction.  The relase function does a
- * kref_put on the device. -ChrisL
+ * with a kref and a per_cpu local_t.  A dma_chan_get is called when a client
+ * signals that it wants to use a channel, and dma_chan_put is called when
+ * a channel is removed or a client using it is unregesitered.  A client can
+ * take extra references per outstanding transaction, as is the case with
+ * the NET DMA client.  The release function does a kref_put on the device.
+ *     -ChrisL, DanW
  */
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/mm.h>
 #include <linux/device.h>
 #include <linux/dmaengine.h>
 #include <linux/hardirq.h>
@@ -66,6 +69,7 @@
 #include <linux/percpu.h>
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
+#include <linux/jiffies.h>
 
 static DEFINE_MUTEX(dma_list_mutex);
 static LIST_HEAD(dma_device_list);
@@ -100,8 +104,19 @@ static ssize_t show_bytes_transferred(struct class_device *cd, char *buf)
 static ssize_t show_in_use(struct class_device *cd, char *buf)
 {
        struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+       int in_use = 0;
+
+       if (unlikely(chan->slow_ref) &&
+               atomic_read(&chan->refcount.refcount) > 1)
+               in_use = 1;
+       else {
+               if (local_read(&(per_cpu_ptr(chan->local,
+                       get_cpu())->refcount)) > 0)
+                       in_use = 1;
+               put_cpu();
+       }
 
-       return sprintf(buf, "%d\n", (chan->client ? 1 : 0));
+       return sprintf(buf, "%d\n", in_use);
 }
 
 static struct class_device_attribute dma_class_attrs[] = {
@@ -127,43 +142,72 @@ static struct class dma_devclass = {
 
 /* --- client and device registration --- */
 
+#define dma_chan_satisfies_mask(chan, mask) \
+       __dma_chan_satisfies_mask((chan), &(mask))
+static int
+__dma_chan_satisfies_mask(struct dma_chan *chan, dma_cap_mask_t *want)
+{
+       dma_cap_mask_t has;
+
+       bitmap_and(has.bits, want->bits, chan->device->cap_mask.bits,
+               DMA_TX_TYPE_END);
+       return bitmap_equal(want->bits, has.bits, DMA_TX_TYPE_END);
+}
+
 /**
- * dma_client_chan_alloc - try to allocate a channel to a client
+ * dma_client_chan_alloc - try to allocate channels to a client
  * @client: &dma_client
  *
  * Called with dma_list_mutex held.
  */
-static struct dma_chan *dma_client_chan_alloc(struct dma_client *client)
+static void dma_client_chan_alloc(struct dma_client *client)
 {
        struct dma_device *device;
        struct dma_chan *chan;
-       unsigned long flags;
        int desc;       /* allocated descriptor count */
+       enum dma_state_client ack;
 
-       /* Find a channel, any DMA engine will do */
-       list_for_each_entry(device, &dma_device_list, global_node) {
+       /* Find a channel */
+       list_for_each_entry(device, &dma_device_list, global_node)
                list_for_each_entry(chan, &device->channels, device_node) {
-                       if (chan->client)
+                       if (!dma_chan_satisfies_mask(chan, client->cap_mask))
                                continue;
 
                        desc = chan->device->device_alloc_chan_resources(chan);
                        if (desc >= 0) {
-                               kref_get(&device->refcount);
-                               kref_init(&chan->refcount);
-                               chan->slow_ref = 0;
-                               INIT_RCU_HEAD(&chan->rcu);
-                               chan->client = client;
-                               spin_lock_irqsave(&client->lock, flags);
-                               list_add_tail_rcu(&chan->client_node,
-                                                 &client->channels);
-                               spin_unlock_irqrestore(&client->lock, flags);
-                               return chan;
+                               ack = client->event_callback(client,
+                                               chan,
+                                               DMA_RESOURCE_AVAILABLE);
+
+                               /* we are done once this client rejects
+                                * an available resource
+                                */
+                               if (ack == DMA_ACK) {
+                                       dma_chan_get(chan);
+                                       kref_get(&device->refcount);
+                               } else if (ack == DMA_NAK)
+                                       return;
                        }
                }
-       }
+}
+
+enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
+{
+       enum dma_status status;
+       unsigned long dma_sync_wait_timeout = jiffies + msecs_to_jiffies(5000);
+
+       dma_async_issue_pending(chan);
+       do {
+               status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
+               if (time_after_eq(jiffies, dma_sync_wait_timeout)) {
+                       printk(KERN_ERR "dma_sync_wait_timeout!\n");
+                       return DMA_ERROR;
+               }
+       } while (status == DMA_IN_PROGRESS);
 
-       return NULL;
+       return status;
 }
+EXPORT_SYMBOL(dma_sync_wait);
 
 /**
  * dma_chan_cleanup - release a DMA channel's resources
@@ -173,7 +217,6 @@ void dma_chan_cleanup(struct kref *kref)
 {
        struct dma_chan *chan = container_of(kref, struct dma_chan, refcount);
        chan->device->device_free_chan_resources(chan);
-       chan->client = NULL;
        kref_put(&chan->device->refcount, dma_async_device_cleanup);
 }
 EXPORT_SYMBOL(dma_chan_cleanup);
@@ -189,7 +232,7 @@ static void dma_chan_free_rcu(struct rcu_head *rcu)
        kref_put(&chan->refcount, dma_chan_cleanup);
 }
 
-static void dma_client_chan_free(struct dma_chan *chan)
+static void dma_chan_release(struct dma_chan *chan)
 {
        atomic_add(0x7FFFFFFF, &chan->refcount.refcount);
        chan->slow_ref = 1;
@@ -197,70 +240,57 @@ static void dma_client_chan_free(struct dma_chan *chan)
 }
 
 /**
- * dma_chans_rebalance - reallocate channels to clients
- *
- * When the number of DMA channel in the system changes,
- * channels need to be rebalanced among clients.
+ * dma_chans_notify_available - broadcast available channels to the clients
  */
-static void dma_chans_rebalance(void)
+static void dma_clients_notify_available(void)
 {
        struct dma_client *client;
-       struct dma_chan *chan;
-       unsigned long flags;
 
        mutex_lock(&dma_list_mutex);
 
-       list_for_each_entry(client, &dma_client_list, global_node) {
-               while (client->chans_desired > client->chan_count) {
-                       chan = dma_client_chan_alloc(client);
-                       if (!chan)
-                               break;
-                       client->chan_count++;
-                       client->event_callback(client,
-                                              chan,
-                                              DMA_RESOURCE_ADDED);
-               }
-               while (client->chans_desired < client->chan_count) {
-                       spin_lock_irqsave(&client->lock, flags);
-                       chan = list_entry(client->channels.next,
-                                         struct dma_chan,
-                                         client_node);
-                       list_del_rcu(&chan->client_node);
-                       spin_unlock_irqrestore(&client->lock, flags);
-                       client->chan_count--;
-                       client->event_callback(client,
-                                              chan,
-                                              DMA_RESOURCE_REMOVED);
-                       dma_client_chan_free(chan);
-               }
-       }
+       list_for_each_entry(client, &dma_client_list, global_node)
+               dma_client_chan_alloc(client);
 
        mutex_unlock(&dma_list_mutex);
 }
 
 /**
- * dma_async_client_register - allocate and register a &dma_client
- * @event_callback: callback for notification of channel addition/removal
+ * dma_chans_notify_available - tell the clients that a channel is going away
+ * @chan: channel on its way out
  */
-struct dma_client *dma_async_client_register(dma_event_callback event_callback)
+static void dma_clients_notify_removed(struct dma_chan *chan)
 {
        struct dma_client *client;
+       enum dma_state_client ack;
 
-       client = kzalloc(sizeof(*client), GFP_KERNEL);
-       if (!client)
-               return NULL;
+       mutex_lock(&dma_list_mutex);
 
-       INIT_LIST_HEAD(&client->channels);
-       spin_lock_init(&client->lock);
-       client->chans_desired = 0;
-       client->chan_count = 0;
-       client->event_callback = event_callback;
+       list_for_each_entry(client, &dma_client_list, global_node) {
+               ack = client->event_callback(client, chan,
+                               DMA_RESOURCE_REMOVED);
+
+               /* client was holding resources for this channel so
+                * free it
+                */
+               if (ack == DMA_ACK) {
+                       dma_chan_put(chan);
+                       kref_put(&chan->device->refcount,
+                               dma_async_device_cleanup);
+               }
+       }
 
+       mutex_unlock(&dma_list_mutex);
+}
+
+/**
+ * dma_async_client_register - register a &dma_client
+ * @client: ptr to a client structure with valid 'event_callback' and 'cap_mask'
+ */
+void dma_async_client_register(struct dma_client *client)
+{
        mutex_lock(&dma_list_mutex);
        list_add_tail(&client->global_node, &dma_client_list);
        mutex_unlock(&dma_list_mutex);
-
-       return client;
 }
 EXPORT_SYMBOL(dma_async_client_register);
 
@@ -272,40 +302,42 @@ EXPORT_SYMBOL(dma_async_client_register);
  */
 void dma_async_client_unregister(struct dma_client *client)
 {
+       struct dma_device *device;
        struct dma_chan *chan;
+       enum dma_state_client ack;
 
        if (!client)
                return;
 
-       rcu_read_lock();
-       list_for_each_entry_rcu(chan, &client->channels, client_node)
-               dma_client_chan_free(chan);
-       rcu_read_unlock();
-
        mutex_lock(&dma_list_mutex);
+       /* free all channels the client is holding */
+       list_for_each_entry(device, &dma_device_list, global_node)
+               list_for_each_entry(chan, &device->channels, device_node) {
+                       ack = client->event_callback(client, chan,
+                               DMA_RESOURCE_REMOVED);
+
+                       if (ack == DMA_ACK) {
+                               dma_chan_put(chan);
+                               kref_put(&chan->device->refcount,
+                                       dma_async_device_cleanup);
+                       }
+               }
+
        list_del(&client->global_node);
        mutex_unlock(&dma_list_mutex);
-
-       kfree(client);
-       dma_chans_rebalance();
 }
 EXPORT_SYMBOL(dma_async_client_unregister);
 
 /**
- * dma_async_client_chan_request - request DMA channels
- * @client: &dma_client
- * @number: count of DMA channels requested
- *
- * Clients call dma_async_client_chan_request() to specify how many
- * DMA channels they need, 0 to free all currently allocated.
- * The resulting allocations/frees are indicated to the client via the
- * event callback.
+ * dma_async_client_chan_request - send all available channels to the
+ * client that satisfy the capability mask
+ * @client - requester
  */
-void dma_async_client_chan_request(struct dma_client *client,
-                       unsigned int number)
+void dma_async_client_chan_request(struct dma_client *client)
 {
-       client->chans_desired = number;
-       dma_chans_rebalance();
+       mutex_lock(&dma_list_mutex);
+       dma_client_chan_alloc(client);
+       mutex_unlock(&dma_list_mutex);
 }
 EXPORT_SYMBOL(dma_async_client_chan_request);
 
@@ -316,12 +348,31 @@ EXPORT_SYMBOL(dma_async_client_chan_request);
 int dma_async_device_register(struct dma_device *device)
 {
        static int id;
-       int chancnt = 0;
+       int chancnt = 0, rc;
        struct dma_chan* chan;
 
        if (!device)
                return -ENODEV;
 
+       /* validate device routines */
+       BUG_ON(dma_has_cap(DMA_MEMCPY, device->cap_mask) &&
+               !device->device_prep_dma_memcpy);
+       BUG_ON(dma_has_cap(DMA_XOR, device->cap_mask) &&
+               !device->device_prep_dma_xor);
+       BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&
+               !device->device_prep_dma_zero_sum);
+       BUG_ON(dma_has_cap(DMA_MEMSET, device->cap_mask) &&
+               !device->device_prep_dma_memset);
+       BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&
+               !device->device_prep_dma_interrupt);
+
+       BUG_ON(!device->device_alloc_chan_resources);
+       BUG_ON(!device->device_free_chan_resources);
+       BUG_ON(!device->device_dependency_added);
+       BUG_ON(!device->device_is_tx_complete);
+       BUG_ON(!device->device_issue_pending);
+       BUG_ON(!device->dev);
+
        init_completion(&device->done);
        kref_init(&device->refcount);
        device->dev_id = id++;
@@ -338,17 +389,38 @@ int dma_async_device_register(struct dma_device *device)
                snprintf(chan->class_dev.class_id, BUS_ID_SIZE, "dma%dchan%d",
                         device->dev_id, chan->chan_id);
 
+               rc = class_device_register(&chan->class_dev);
+               if (rc) {
+                       chancnt--;
+                       free_percpu(chan->local);
+                       chan->local = NULL;
+                       goto err_out;
+               }
+
                kref_get(&device->refcount);
-               class_device_register(&chan->class_dev);
+               kref_init(&chan->refcount);
+               chan->slow_ref = 0;
+               INIT_RCU_HEAD(&chan->rcu);
        }
 
        mutex_lock(&dma_list_mutex);
        list_add_tail(&device->global_node, &dma_device_list);
        mutex_unlock(&dma_list_mutex);
 
-       dma_chans_rebalance();
+       dma_clients_notify_available();
 
        return 0;
+
+err_out:
+       list_for_each_entry(chan, &device->channels, device_node) {
+               if (chan->local == NULL)
+                       continue;
+               kref_put(&device->refcount, dma_async_device_cleanup);
+               class_device_unregister(&chan->class_dev);
+               chancnt--;
+               free_percpu(chan->local);
+       }
+       return rc;
 }
 EXPORT_SYMBOL(dma_async_device_register);
 
@@ -371,32 +443,165 @@ static void dma_async_device_cleanup(struct kref *kref)
 void dma_async_device_unregister(struct dma_device *device)
 {
        struct dma_chan *chan;
-       unsigned long flags;
 
        mutex_lock(&dma_list_mutex);
        list_del(&device->global_node);
        mutex_unlock(&dma_list_mutex);
 
        list_for_each_entry(chan, &device->channels, device_node) {
-               if (chan->client) {
-                       spin_lock_irqsave(&chan->client->lock, flags);
-                       list_del(&chan->client_node);
-                       chan->client->chan_count--;
-                       spin_unlock_irqrestore(&chan->client->lock, flags);
-                       chan->client->event_callback(chan->client,
-                                                    chan,
-                                                    DMA_RESOURCE_REMOVED);
-                       dma_client_chan_free(chan);
-               }
+               dma_clients_notify_removed(chan);
                class_device_unregister(&chan->class_dev);
+               dma_chan_release(chan);
        }
-       dma_chans_rebalance();
 
        kref_put(&device->refcount, dma_async_device_cleanup);
        wait_for_completion(&device->done);
 }
 EXPORT_SYMBOL(dma_async_device_unregister);
 
+/**
+ * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
+ * @chan: DMA channel to offload copy to
+ * @dest: destination address (virtual)
+ * @src: source address (virtual)
+ * @len: length
+ *
+ * Both @dest and @src must be mappable to a bus address according to the
+ * DMA mapping API rules for streaming mappings.
+ * Both @dest and @src must stay memory resident (kernel memory or locked
+ * user space pages).
+ */
+dma_cookie_t
+dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
+                       void *src, size_t len)
+{
+       struct dma_device *dev = chan->device;
+       struct dma_async_tx_descriptor *tx;
+       dma_addr_t addr;
+       dma_cookie_t cookie;
+       int cpu;
+
+       tx = dev->device_prep_dma_memcpy(chan, len, 0);
+       if (!tx)
+               return -ENOMEM;
+
+       tx->ack = 1;
+       tx->callback = NULL;
+       addr = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
+       tx->tx_set_src(addr, tx, 0);
+       addr = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
+       tx->tx_set_dest(addr, tx, 0);
+       cookie = tx->tx_submit(tx);
+
+       cpu = get_cpu();
+       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+       put_cpu();
+
+       return cookie;
+}
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
+
+/**
+ * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
+ * @chan: DMA channel to offload copy to
+ * @page: destination page
+ * @offset: offset in page to copy to
+ * @kdata: source address (virtual)
+ * @len: length
+ *
+ * Both @page/@offset and @kdata must be mappable to a bus address according
+ * to the DMA mapping API rules for streaming mappings.
+ * Both @page/@offset and @kdata must stay memory resident (kernel memory or
+ * locked user space pages)
+ */
+dma_cookie_t
+dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
+                       unsigned int offset, void *kdata, size_t len)
+{
+       struct dma_device *dev = chan->device;
+       struct dma_async_tx_descriptor *tx;
+       dma_addr_t addr;
+       dma_cookie_t cookie;
+       int cpu;
+
+       tx = dev->device_prep_dma_memcpy(chan, len, 0);
+       if (!tx)
+               return -ENOMEM;
+
+       tx->ack = 1;
+       tx->callback = NULL;
+       addr = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
+       tx->tx_set_src(addr, tx, 0);
+       addr = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
+       tx->tx_set_dest(addr, tx, 0);
+       cookie = tx->tx_submit(tx);
+
+       cpu = get_cpu();
+       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+       put_cpu();
+
+       return cookie;
+}
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
+
+/**
+ * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
+ * @chan: DMA channel to offload copy to
+ * @dest_pg: destination page
+ * @dest_off: offset in page to copy to
+ * @src_pg: source page
+ * @src_off: offset in page to copy from
+ * @len: length
+ *
+ * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
+ * address according to the DMA mapping API rules for streaming mappings.
+ * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
+ * (kernel memory or locked user space pages).
+ */
+dma_cookie_t
+dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
+       unsigned int dest_off, struct page *src_pg, unsigned int src_off,
+       size_t len)
+{
+       struct dma_device *dev = chan->device;
+       struct dma_async_tx_descriptor *tx;
+       dma_addr_t addr;
+       dma_cookie_t cookie;
+       int cpu;
+
+       tx = dev->device_prep_dma_memcpy(chan, len, 0);
+       if (!tx)
+               return -ENOMEM;
+
+       tx->ack = 1;
+       tx->callback = NULL;
+       addr = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
+       tx->tx_set_src(addr, tx, 0);
+       addr = dma_map_page(dev->dev, dest_pg, dest_off, len, DMA_FROM_DEVICE);
+       tx->tx_set_dest(addr, tx, 0);
+       cookie = tx->tx_submit(tx);
+
+       cpu = get_cpu();
+       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+       put_cpu();
+
+       return cookie;
+}
+EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg);
+
+void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+       struct dma_chan *chan)
+{
+       tx->chan = chan;
+       spin_lock_init(&tx->lock);
+       INIT_LIST_HEAD(&tx->depend_node);
+       INIT_LIST_HEAD(&tx->depend_list);
+}
+EXPORT_SYMBOL(dma_async_tx_descriptor_init);
+
 static int __init dma_bus_init(void)
 {
        mutex_init(&dma_list_mutex);
index 850014139556c853a4c4018fb81fdd69d2f50ff0..5fbe56b5cea09bb01f74e40488f63187dd851c1f 100644 (file)
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include "ioatdma.h"
-#include "ioatdma_io.h"
 #include "ioatdma_registers.h"
 #include "ioatdma_hw.h"
 
 #define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
 #define to_ioat_device(dev) container_of(dev, struct ioat_device, common)
 #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
+#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
 
 /* internal functions */
 static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void ioat_shutdown(struct pci_dev *pdev);
 static void __devexit ioat_remove(struct pci_dev *pdev);
 
 static int enumerate_dma_channels(struct ioat_device *device)
@@ -51,8 +52,8 @@ static int enumerate_dma_channels(struct ioat_device *device)
        int i;
        struct ioat_dma_chan *ioat_chan;
 
-       device->common.chancnt = ioatdma_read8(device, IOAT_CHANCNT_OFFSET);
-       xfercap_scale = ioatdma_read8(device, IOAT_XFERCAP_OFFSET);
+       device->common.chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);
+       xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
        xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
 
        for (i = 0; i < device->common.chancnt; i++) {
@@ -71,13 +72,79 @@ static int enumerate_dma_channels(struct ioat_device *device)
                INIT_LIST_HEAD(&ioat_chan->used_desc);
                /* This should be made common somewhere in dmaengine.c */
                ioat_chan->common.device = &device->common;
-               ioat_chan->common.client = NULL;
                list_add_tail(&ioat_chan->common.device_node,
                              &device->common.channels);
        }
        return device->common.chancnt;
 }
 
+static void
+ioat_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
+{
+       struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+
+       pci_unmap_addr_set(desc, src, addr);
+
+       list_for_each_entry(iter, &desc->async_tx.tx_list, node) {
+               iter->hw->src_addr = addr;
+               addr += ioat_chan->xfercap;
+       }
+
+}
+
+static void
+ioat_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
+{
+       struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+
+       pci_unmap_addr_set(desc, dst, addr);
+
+       list_for_each_entry(iter, &desc->async_tx.tx_list, node) {
+               iter->hw->dst_addr = addr;
+               addr += ioat_chan->xfercap;
+       }
+}
+
+static dma_cookie_t
+ioat_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+       struct ioat_desc_sw *desc = tx_to_ioat_desc(tx);
+       int append = 0;
+       dma_cookie_t cookie;
+       struct ioat_desc_sw *group_start;
+
+       group_start = list_entry(desc->async_tx.tx_list.next,
+                                struct ioat_desc_sw, node);
+       spin_lock_bh(&ioat_chan->desc_lock);
+       /* cookie incr and addition to used_list must be atomic */
+       cookie = ioat_chan->common.cookie;
+       cookie++;
+       if (cookie < 0)
+               cookie = 1;
+       ioat_chan->common.cookie = desc->async_tx.cookie = cookie;
+
+       /* write address into NextDescriptor field of last desc in chain */
+       to_ioat_desc(ioat_chan->used_desc.prev)->hw->next =
+                                               group_start->async_tx.phys;
+       list_splice_init(&desc->async_tx.tx_list, ioat_chan->used_desc.prev);
+
+       ioat_chan->pending += desc->tx_cnt;
+       if (ioat_chan->pending >= 4) {
+               append = 1;
+               ioat_chan->pending = 0;
+       }
+       spin_unlock_bh(&ioat_chan->desc_lock);
+
+       if (append)
+               writeb(IOAT_CHANCMD_APPEND,
+                       ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
+       
+       return cookie;
+}
+
 static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
        struct ioat_dma_chan *ioat_chan,
        gfp_t flags)
@@ -99,8 +166,13 @@ static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
        }
 
        memset(desc, 0, sizeof(*desc));
+       dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common);
+       desc_sw->async_tx.tx_set_src = ioat_set_src;
+       desc_sw->async_tx.tx_set_dest = ioat_set_dest;
+       desc_sw->async_tx.tx_submit = ioat_tx_submit;
+       INIT_LIST_HEAD(&desc_sw->async_tx.tx_list);
        desc_sw->hw = desc;
-       desc_sw->phys = phys;
+       desc_sw->async_tx.phys = phys;
 
        return desc_sw;
 }
@@ -123,7 +195,7 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
         * In-use bit automatically set by reading chanctrl
         * If 0, we got it, if 1, someone else did
         */
-       chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+       chanctrl = readw(ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
        if (chanctrl & IOAT_CHANCTRL_CHANNEL_IN_USE)
                return -EBUSY;
 
@@ -132,12 +204,12 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
                IOAT_CHANCTRL_ERR_INT_EN |
                IOAT_CHANCTRL_ANY_ERR_ABORT_EN |
                IOAT_CHANCTRL_ERR_COMPLETION_EN;
-        ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+        writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
 
-       chanerr = ioatdma_chan_read32(ioat_chan, IOAT_CHANERR_OFFSET);
+       chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
        if (chanerr) {
                printk("IOAT: CHANERR = %x, clearing\n", chanerr);
-               ioatdma_chan_write32(ioat_chan, IOAT_CHANERR_OFFSET, chanerr);
+               writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
        }
 
        /* Allocate descriptors */
@@ -161,10 +233,10 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
                               &ioat_chan->completion_addr);
        memset(ioat_chan->completion_virt, 0,
               sizeof(*ioat_chan->completion_virt));
-       ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_LOW,
-                      ((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF);
-       ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_HIGH,
-                      ((u64) ioat_chan->completion_addr) >> 32);
+       writel(((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF,
+              ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_LOW);
+       writel(((u64) ioat_chan->completion_addr) >> 32,
+              ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
 
        ioat_start_null_desc(ioat_chan);
        return i;
@@ -182,18 +254,20 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
 
        ioat_dma_memcpy_cleanup(ioat_chan);
 
-       ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET);
+       writeb(IOAT_CHANCMD_RESET, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
 
        spin_lock_bh(&ioat_chan->desc_lock);
        list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) {
                in_use_descs++;
                list_del(&desc->node);
-               pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+               pci_pool_free(ioat_device->dma_pool, desc->hw,
+                             desc->async_tx.phys);
                kfree(desc);
        }
        list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) {
                list_del(&desc->node);
-               pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+               pci_pool_free(ioat_device->dma_pool, desc->hw,
+                             desc->async_tx.phys);
                kfree(desc);
        }
        spin_unlock_bh(&ioat_chan->desc_lock);
@@ -210,50 +284,30 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
        ioat_chan->last_completion = ioat_chan->completion_addr = 0;
 
        /* Tell hw the chan is free */
-       chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+       chanctrl = readw(ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
        chanctrl &= ~IOAT_CHANCTRL_CHANNEL_IN_USE;
-       ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+       writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
-/**
- * do_ioat_dma_memcpy - actual function that initiates a IOAT DMA transaction
- * @ioat_chan: IOAT DMA channel handle
- * @dest: DMA destination address
- * @src: DMA source address
- * @len: transaction length in bytes
- */
-
-static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan,
-                                       dma_addr_t dest,
-                                       dma_addr_t src,
-                                       size_t len)
+static struct dma_async_tx_descriptor *
+ioat_dma_prep_memcpy(struct dma_chan *chan, size_t len, int int_en)
 {
-       struct ioat_desc_sw *first;
-       struct ioat_desc_sw *prev;
-       struct ioat_desc_sw *new;
-       dma_cookie_t cookie;
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+       struct ioat_desc_sw *first, *prev, *new;
        LIST_HEAD(new_chain);
        u32 copy;
        size_t orig_len;
-       dma_addr_t orig_src, orig_dst;
-       unsigned int desc_count = 0;
-       unsigned int append = 0;
-
-       if (!ioat_chan || !dest || !src)
-               return -EFAULT;
+       int desc_count = 0;
 
        if (!len)
-               return ioat_chan->common.cookie;
+               return NULL;
 
        orig_len = len;
-       orig_src = src;
-       orig_dst = dest;
 
        first = NULL;
        prev = NULL;
 
        spin_lock_bh(&ioat_chan->desc_lock);
-
        while (len) {
                if (!list_empty(&ioat_chan->free_desc)) {
                        new = to_ioat_desc(ioat_chan->free_desc.next);
@@ -270,141 +324,36 @@ static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan,
 
                new->hw->size = copy;
                new->hw->ctl = 0;
-               new->hw->src_addr = src;
-               new->hw->dst_addr = dest;
-               new->cookie = 0;
+               new->async_tx.cookie = 0;
+               new->async_tx.ack = 1;
 
                /* chain together the physical address list for the HW */
                if (!first)
                        first = new;
                else
-                       prev->hw->next = (u64) new->phys;
+                       prev->hw->next = (u64) new->async_tx.phys;
 
                prev = new;
-
                len  -= copy;
-               dest += copy;
-               src  += copy;
-
                list_add_tail(&new->node, &new_chain);
                desc_count++;
        }
-       new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
-       new->hw->next = 0;
 
-       /* cookie incr and addition to used_list must be atomic */
+       list_splice(&new_chain, &new->async_tx.tx_list);
 
-       cookie = ioat_chan->common.cookie;
-       cookie++;
-       if (cookie < 0)
-               cookie = 1;
-       ioat_chan->common.cookie = new->cookie = cookie;
+       new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+       new->hw->next = 0;
+       new->tx_cnt = desc_count;
+       new->async_tx.ack = 0; /* client is in control of this ack */
+       new->async_tx.cookie = -EBUSY;
 
-       pci_unmap_addr_set(new, src, orig_src);
-       pci_unmap_addr_set(new, dst, orig_dst);
        pci_unmap_len_set(new, src_len, orig_len);
        pci_unmap_len_set(new, dst_len, orig_len);
-
-       /* write address into NextDescriptor field of last desc in chain */
-       to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->phys;
-       list_splice_init(&new_chain, ioat_chan->used_desc.prev);
-
-       ioat_chan->pending += desc_count;
-       if (ioat_chan->pending >= 20) {
-               append = 1;
-               ioat_chan->pending = 0;
-       }
-
        spin_unlock_bh(&ioat_chan->desc_lock);
 
-       if (append)
-               ioatdma_chan_write8(ioat_chan,
-                                   IOAT_CHANCMD_OFFSET,
-                                   IOAT_CHANCMD_APPEND);
-       return cookie;
-}
-
-/**
- * ioat_dma_memcpy_buf_to_buf - wrapper that takes src & dest bufs
- * @chan: IOAT DMA channel handle
- * @dest: DMA destination address
- * @src: DMA source address
- * @len: transaction length in bytes
- */
-
-static dma_cookie_t ioat_dma_memcpy_buf_to_buf(struct dma_chan *chan,
-                                               void *dest,
-                                               void *src,
-                                               size_t len)
-{
-       dma_addr_t dest_addr;
-       dma_addr_t src_addr;
-       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
-       dest_addr = pci_map_single(ioat_chan->device->pdev,
-               dest, len, PCI_DMA_FROMDEVICE);
-       src_addr = pci_map_single(ioat_chan->device->pdev,
-               src, len, PCI_DMA_TODEVICE);
-
-       return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+       return new ? &new->async_tx : NULL;
 }
 
-/**
- * ioat_dma_memcpy_buf_to_pg - wrapper, copying from a buf to a page
- * @chan: IOAT DMA channel handle
- * @page: pointer to the page to copy to
- * @offset: offset into that page
- * @src: DMA source address
- * @len: transaction length in bytes
- */
-
-static dma_cookie_t ioat_dma_memcpy_buf_to_pg(struct dma_chan *chan,
-                                              struct page *page,
-                                              unsigned int offset,
-                                              void *src,
-                                              size_t len)
-{
-       dma_addr_t dest_addr;
-       dma_addr_t src_addr;
-       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
-       dest_addr = pci_map_page(ioat_chan->device->pdev,
-               page, offset, len, PCI_DMA_FROMDEVICE);
-       src_addr = pci_map_single(ioat_chan->device->pdev,
-               src, len, PCI_DMA_TODEVICE);
-
-       return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
-}
-
-/**
- * ioat_dma_memcpy_pg_to_pg - wrapper, copying between two pages
- * @chan: IOAT DMA channel handle
- * @dest_pg: pointer to the page to copy to
- * @dest_off: offset into that page
- * @src_pg: pointer to the page to copy from
- * @src_off: offset into that page
- * @len: transaction length in bytes. This is guaranteed not to make a copy
- *      across a page boundary.
- */
-
-static dma_cookie_t ioat_dma_memcpy_pg_to_pg(struct dma_chan *chan,
-                                             struct page *dest_pg,
-                                             unsigned int dest_off,
-                                             struct page *src_pg,
-                                             unsigned int src_off,
-                                             size_t len)
-{
-       dma_addr_t dest_addr;
-       dma_addr_t src_addr;
-       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
-       dest_addr = pci_map_page(ioat_chan->device->pdev,
-               dest_pg, dest_off, len, PCI_DMA_FROMDEVICE);
-       src_addr = pci_map_page(ioat_chan->device->pdev,
-               src_pg, src_off, len, PCI_DMA_TODEVICE);
-
-       return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
-}
 
 /**
  * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended descriptors to hw
@@ -417,9 +366,8 @@ static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan)
 
        if (ioat_chan->pending != 0) {
                ioat_chan->pending = 0;
-               ioatdma_chan_write8(ioat_chan,
-                                   IOAT_CHANCMD_OFFSET,
-                                   IOAT_CHANCMD_APPEND);
+               writeb(IOAT_CHANCMD_APPEND,
+                      ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
        }
 }
 
@@ -449,7 +397,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
        if ((chan->completion_virt->full & IOAT_CHANSTS_DMA_TRANSFER_STATUS) ==
                IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) {
                printk("IOAT: Channel halted, chanerr = %x\n",
-                       ioatdma_chan_read32(chan, IOAT_CHANERR_OFFSET));
+                       readl(chan->reg_base + IOAT_CHANERR_OFFSET));
 
                /* TODO do something to salvage the situation */
        }
@@ -467,8 +415,8 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
                 * exceeding xfercap, perhaps. If so, only the last one will
                 * have a cookie, and require unmapping.
                 */
-               if (desc->cookie) {
-                       cookie = desc->cookie;
+               if (desc->async_tx.cookie) {
+                       cookie = desc->async_tx.cookie;
 
                        /* yes we are unmapping both _page and _single alloc'd
                           regions with unmap_page. Is this *really* that bad?
@@ -483,14 +431,19 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
                                        PCI_DMA_TODEVICE);
                }
 
-               if (desc->phys != phys_complete) {
-                       /* a completed entry, but not the last, so cleanup */
-                       list_del(&desc->node);
-                       list_add_tail(&desc->node, &chan->free_desc);
+               if (desc->async_tx.phys != phys_complete) {
+                       /* a completed entry, but not the last, so cleanup
+                        * if the client is done with the descriptor
+                        */
+                       if (desc->async_tx.ack) {
+                               list_del(&desc->node);
+                               list_add_tail(&desc->node, &chan->free_desc);
+                       } else
+                               desc->async_tx.cookie = 0;
                } else {
                        /* last used desc. Do not remove, so we can append from
                           it, but don't look at it next time, either */
-                       desc->cookie = 0;
+                       desc->async_tx.cookie = 0;
 
                        /* TODO check status bits? */
                        break;
@@ -506,6 +459,17 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
        spin_unlock(&chan->cleanup_lock);
 }
 
+static void ioat_dma_dependency_added(struct dma_chan *chan)
+{
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+       spin_lock_bh(&ioat_chan->desc_lock);
+       if (ioat_chan->pending == 0) {
+               spin_unlock_bh(&ioat_chan->desc_lock);
+               ioat_dma_memcpy_cleanup(ioat_chan);
+       } else
+               spin_unlock_bh(&ioat_chan->desc_lock);
+}
+
 /**
  * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
  * @chan: IOAT DMA channel handle
@@ -553,6 +517,8 @@ static enum dma_status ioat_dma_is_complete(struct dma_chan *chan,
 
 static struct pci_device_id ioat_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
+       { PCI_DEVICE(PCI_VENDOR_ID_UNISYS,
+                    PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) },
        { 0, }
 };
 
@@ -560,6 +526,7 @@ static struct pci_driver ioat_pci_driver = {
        .name   = "ioatdma",
        .id_table = ioat_pci_tbl,
        .probe  = ioat_probe,
+       .shutdown = ioat_shutdown,
        .remove = __devexit_p(ioat_remove),
 };
 
@@ -569,21 +536,21 @@ static irqreturn_t ioat_do_interrupt(int irq, void *data)
        unsigned long attnstatus;
        u8 intrctrl;
 
-       intrctrl = ioatdma_read8(instance, IOAT_INTRCTRL_OFFSET);
+       intrctrl = readb(instance->reg_base + IOAT_INTRCTRL_OFFSET);
 
        if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN))
                return IRQ_NONE;
 
        if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) {
-               ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+               writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
                return IRQ_NONE;
        }
 
-       attnstatus = ioatdma_read32(instance, IOAT_ATTNSTATUS_OFFSET);
+       attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
 
        printk(KERN_ERR "ioatdma error: interrupt! status %lx\n", attnstatus);
 
-       ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+       writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
        return IRQ_HANDLED;
 }
 
@@ -607,19 +574,17 @@ static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan)
 
        desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
        desc->hw->next = 0;
+       desc->async_tx.ack = 1;
 
        list_add_tail(&desc->node, &ioat_chan->used_desc);
        spin_unlock_bh(&ioat_chan->desc_lock);
 
-#if (BITS_PER_LONG == 64)
-       ioatdma_chan_write64(ioat_chan, IOAT_CHAINADDR_OFFSET, desc->phys);
-#else
-       ioatdma_chan_write32(ioat_chan,
-                            IOAT_CHAINADDR_OFFSET_LOW,
-                            (u32) desc->phys);
-       ioatdma_chan_write32(ioat_chan, IOAT_CHAINADDR_OFFSET_HIGH, 0);
-#endif
-       ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_START);
+       writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+              ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_LOW);
+       writel(((u64) desc->async_tx.phys) >> 32,
+              ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_HIGH);
+
+       writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
 }
 
 /*
@@ -633,6 +598,8 @@ static int ioat_self_test(struct ioat_device *device)
        u8 *src;
        u8 *dest;
        struct dma_chan *dma_chan;
+       struct dma_async_tx_descriptor *tx;
+       dma_addr_t addr;
        dma_cookie_t cookie;
        int err = 0;
 
@@ -658,7 +625,15 @@ static int ioat_self_test(struct ioat_device *device)
                goto out;
        }
 
-       cookie = ioat_dma_memcpy_buf_to_buf(dma_chan, dest, src, IOAT_TEST_SIZE);
+       tx = ioat_dma_prep_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
+       async_tx_ack(tx);
+       addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,
+                       DMA_TO_DEVICE);
+       ioat_set_src(addr, tx, 0);
+       addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
+                       DMA_FROM_DEVICE);
+       ioat_set_dest(addr, tx, 0);
+       cookie = ioat_tx_submit(tx);
        ioat_dma_memcpy_issue_pending(dma_chan);
        msleep(1);
 
@@ -748,19 +723,20 @@ static int __devinit ioat_probe(struct pci_dev *pdev,
 
        device->reg_base = reg_base;
 
-       ioatdma_write8(device, IOAT_INTRCTRL_OFFSET, IOAT_INTRCTRL_MASTER_INT_EN);
+       writeb(IOAT_INTRCTRL_MASTER_INT_EN, device->reg_base + IOAT_INTRCTRL_OFFSET);
        pci_set_master(pdev);
 
        INIT_LIST_HEAD(&device->common.channels);
        enumerate_dma_channels(device);
 
+       dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
        device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources;
        device->common.device_free_chan_resources = ioat_dma_free_chan_resources;
-       device->common.device_memcpy_buf_to_buf = ioat_dma_memcpy_buf_to_buf;
-       device->common.device_memcpy_buf_to_pg = ioat_dma_memcpy_buf_to_pg;
-       device->common.device_memcpy_pg_to_pg = ioat_dma_memcpy_pg_to_pg;
-       device->common.device_memcpy_complete = ioat_dma_is_complete;
-       device->common.device_memcpy_issue_pending = ioat_dma_memcpy_issue_pending;
+       device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy;
+       device->common.device_is_tx_complete = ioat_dma_is_complete;
+       device->common.device_issue_pending = ioat_dma_memcpy_issue_pending;
+       device->common.device_dependency_added = ioat_dma_dependency_added;
+       device->common.dev = &pdev->dev;
        printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n",
                device->common.chancnt);
 
@@ -787,9 +763,20 @@ err_request_regions:
 err_set_dma_mask:
        pci_disable_device(pdev);
 err_enable_device:
+
+       printk(KERN_ERR "Intel(R) I/OAT DMA Engine initialization failed\n");
+
        return err;
 }
 
+static void ioat_shutdown(struct pci_dev *pdev)
+{
+       struct ioat_device *device;
+       device = pci_get_drvdata(pdev);
+
+       dma_async_device_unregister(&device->common);
+}
+
 static void __devexit ioat_remove(struct pci_dev *pdev)
 {
        struct ioat_device *device;
@@ -818,7 +805,7 @@ static void __devexit ioat_remove(struct pci_dev *pdev)
 }
 
 /* MODULE API */
-MODULE_VERSION("1.7");
+MODULE_VERSION("1.9");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Intel Corporation");
 
index 62b26a9be4c9d01cb4d4abb364a1252d1c938c74..d3726478031a4ffd3c66db68e5e3361792658fb5 100644 (file)
@@ -30,9 +30,6 @@
 
 #define IOAT_LOW_COMPLETION_MASK       0xffffffc0
 
-extern struct list_head dma_device_list;
-extern struct list_head dma_client_list;
-
 /**
  * struct ioat_device - internal representation of a IOAT device
  * @pdev: PCI-Express device
@@ -105,21 +102,20 @@ struct ioat_dma_chan {
 /**
  * struct ioat_desc_sw - wrapper around hardware descriptor
  * @hw: hardware DMA descriptor
- * @node:
- * @cookie:
- * @phys:
+ * @node: this descriptor will either be on the free list,
+ *     or attached to a transaction list (async_tx.tx_list)
+ * @tx_cnt: number of descriptors required to complete the transaction
+ * @async_tx: the generic software descriptor for all engines
  */
-
 struct ioat_desc_sw {
        struct ioat_dma_descriptor *hw;
        struct list_head node;
-       dma_cookie_t cookie;
-       dma_addr_t phys;
+       int tx_cnt;
        DECLARE_PCI_UNMAP_ADDR(src)
        DECLARE_PCI_UNMAP_LEN(src_len)
        DECLARE_PCI_UNMAP_ADDR(dst)
        DECLARE_PCI_UNMAP_LEN(dst_len)
+       struct dma_async_tx_descriptor async_tx;
 };
 
 #endif /* IOATDMA_H */
-
diff --git a/drivers/dma/ioatdma_io.h b/drivers/dma/ioatdma_io.h
deleted file mode 100644 (file)
index c0b4bf6..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called COPYING.
- */
-#ifndef IOATDMA_IO_H
-#define IOATDMA_IO_H
-
-#include <asm/io.h>
-
-/*
- * device and per-channel MMIO register read and write functions
- * this is a lot of anoying inline functions, but it's typesafe
- */
-
-static inline u8 ioatdma_read8(struct ioat_device *device,
-                               unsigned int offset)
-{
-       return readb(device->reg_base + offset);
-}
-
-static inline u16 ioatdma_read16(struct ioat_device *device,
-                                 unsigned int offset)
-{
-       return readw(device->reg_base + offset);
-}
-
-static inline u32 ioatdma_read32(struct ioat_device *device,
-                                 unsigned int offset)
-{
-       return readl(device->reg_base + offset);
-}
-
-static inline void ioatdma_write8(struct ioat_device *device,
-                                  unsigned int offset, u8 value)
-{
-       writeb(value, device->reg_base + offset);
-}
-
-static inline void ioatdma_write16(struct ioat_device *device,
-                                   unsigned int offset, u16 value)
-{
-       writew(value, device->reg_base + offset);
-}
-
-static inline void ioatdma_write32(struct ioat_device *device,
-                                   unsigned int offset, u32 value)
-{
-       writel(value, device->reg_base + offset);
-}
-
-static inline u8 ioatdma_chan_read8(struct ioat_dma_chan *chan,
-                                    unsigned int offset)
-{
-       return readb(chan->reg_base + offset);
-}
-
-static inline u16 ioatdma_chan_read16(struct ioat_dma_chan *chan,
-                                      unsigned int offset)
-{
-       return readw(chan->reg_base + offset);
-}
-
-static inline u32 ioatdma_chan_read32(struct ioat_dma_chan *chan,
-                                      unsigned int offset)
-{
-       return readl(chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write8(struct ioat_dma_chan *chan,
-                                       unsigned int offset, u8 value)
-{
-       writeb(value, chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write16(struct ioat_dma_chan *chan,
-                                        unsigned int offset, u16 value)
-{
-       writew(value, chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write32(struct ioat_dma_chan *chan,
-                                        unsigned int offset, u32 value)
-{
-       writel(value, chan->reg_base + offset);
-}
-
-#if (BITS_PER_LONG == 64)
-static inline u64 ioatdma_chan_read64(struct ioat_dma_chan *chan,
-                                      unsigned int offset)
-{
-       return readq(chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write64(struct ioat_dma_chan *chan,
-                                        unsigned int offset, u64 value)
-{
-       writeq(value, chan->reg_base + offset);
-}
-#endif
-
-#endif /* IOATDMA_IO_H */
-
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
new file mode 100644 (file)
index 0000000..5a1d426
--- /dev/null
@@ -0,0 +1,1467 @@
+/*
+ * offload engine driver for the Intel Xscale series of i/o processors
+ * Copyright Â© 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+/*
+ * This driver supports the asynchrounous DMA copy and RAID engines available
+ * on the Intel Xscale(R) family of I/O Processors (IOP 32x, 33x, 134x)
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/async_tx.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/memory.h>
+#include <linux/ioport.h>
+
+#include <asm/arch/adma.h>
+
+#define to_iop_adma_chan(chan) container_of(chan, struct iop_adma_chan, common)
+#define to_iop_adma_device(dev) \
+       container_of(dev, struct iop_adma_device, common)
+#define tx_to_iop_adma_slot(tx) \
+       container_of(tx, struct iop_adma_desc_slot, async_tx)
+
+/**
+ * iop_adma_free_slots - flags descriptor slots for reuse
+ * @slot: Slot to free
+ * Caller must hold &iop_chan->lock while calling this function
+ */
+static void iop_adma_free_slots(struct iop_adma_desc_slot *slot)
+{
+       int stride = slot->slots_per_op;
+
+       while (stride--) {
+               slot->slots_per_op = 0;
+               slot = list_entry(slot->slot_node.next,
+                               struct iop_adma_desc_slot,
+                               slot_node);
+       }
+}
+
+static dma_cookie_t
+iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
+       struct iop_adma_chan *iop_chan, dma_cookie_t cookie)
+{
+       BUG_ON(desc->async_tx.cookie < 0);
+       spin_lock_bh(&desc->async_tx.lock);
+       if (desc->async_tx.cookie > 0) {
+               cookie = desc->async_tx.cookie;
+               desc->async_tx.cookie = 0;
+
+               /* call the callback (must not sleep or submit new
+                * operations to this channel)
+                */
+               if (desc->async_tx.callback)
+                       desc->async_tx.callback(
+                               desc->async_tx.callback_param);
+
+               /* unmap dma addresses
+                * (unmap_single vs unmap_page?)
+                */
+               if (desc->group_head && desc->unmap_len) {
+                       struct iop_adma_desc_slot *unmap = desc->group_head;
+                       struct device *dev =
+                               &iop_chan->device->pdev->dev;
+                       u32 len = unmap->unmap_len;
+                       u32 src_cnt = unmap->unmap_src_cnt;
+                       dma_addr_t addr = iop_desc_get_dest_addr(unmap,
+                               iop_chan);
+
+                       dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+                       while (src_cnt--) {
+                               addr = iop_desc_get_src_addr(unmap,
+                                                       iop_chan,
+                                                       src_cnt);
+                               dma_unmap_page(dev, addr, len,
+                                       DMA_TO_DEVICE);
+                       }
+                       desc->group_head = NULL;
+               }
+       }
+
+       /* run dependent operations */
+       async_tx_run_dependencies(&desc->async_tx);
+       spin_unlock_bh(&desc->async_tx.lock);
+
+       return cookie;
+}
+
+static int
+iop_adma_clean_slot(struct iop_adma_desc_slot *desc,
+       struct iop_adma_chan *iop_chan)
+{
+       /* the client is allowed to attach dependent operations
+        * until 'ack' is set
+        */
+       if (!desc->async_tx.ack)
+               return 0;
+
+       /* leave the last descriptor in the chain
+        * so we can append to it
+        */
+       if (desc->chain_node.next == &iop_chan->chain)
+               return 1;
+
+       dev_dbg(iop_chan->device->common.dev,
+               "\tfree slot: %d slots_per_op: %d\n",
+               desc->idx, desc->slots_per_op);
+
+       list_del(&desc->chain_node);
+       iop_adma_free_slots(desc);
+
+       return 0;
+}
+
+static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+{
+       struct iop_adma_desc_slot *iter, *_iter, *grp_start = NULL;
+       dma_cookie_t cookie = 0;
+       u32 current_desc = iop_chan_get_current_descriptor(iop_chan);
+       int busy = iop_chan_is_busy(iop_chan);
+       int seen_current = 0, slot_cnt = 0, slots_per_op = 0;
+
+       dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+       /* free completed slots from the chain starting with
+        * the oldest descriptor
+        */
+       list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
+                                       chain_node) {
+               pr_debug("\tcookie: %d slot: %d busy: %d "
+                       "this_desc: %#x next_desc: %#x ack: %d\n",
+                       iter->async_tx.cookie, iter->idx, busy,
+                       iter->async_tx.phys, iop_desc_get_next_desc(iter),
+                       iter->async_tx.ack);
+               prefetch(_iter);
+               prefetch(&_iter->async_tx);
+
+               /* do not advance past the current descriptor loaded into the
+                * hardware channel, subsequent descriptors are either in
+                * process or have not been submitted
+                */
+               if (seen_current)
+                       break;
+
+               /* stop the search if we reach the current descriptor and the
+                * channel is busy, or if it appears that the current descriptor
+                * needs to be re-read (i.e. has been appended to)
+                */
+               if (iter->async_tx.phys == current_desc) {
+                       BUG_ON(seen_current++);
+                       if (busy || iop_desc_get_next_desc(iter))
+                               break;
+               }
+
+               /* detect the start of a group transaction */
+               if (!slot_cnt && !slots_per_op) {
+                       slot_cnt = iter->slot_cnt;
+                       slots_per_op = iter->slots_per_op;
+                       if (slot_cnt <= slots_per_op) {
+                               slot_cnt = 0;
+                               slots_per_op = 0;
+                       }
+               }
+
+               if (slot_cnt) {
+                       pr_debug("\tgroup++\n");
+                       if (!grp_start)
+                               grp_start = iter;
+                       slot_cnt -= slots_per_op;
+               }
+
+               /* all the members of a group are complete */
+               if (slots_per_op != 0 && slot_cnt == 0) {
+                       struct iop_adma_desc_slot *grp_iter, *_grp_iter;
+                       int end_of_chain = 0;
+                       pr_debug("\tgroup end\n");
+
+                       /* collect the total results */
+                       if (grp_start->xor_check_result) {
+                               u32 zero_sum_result = 0;
+                               slot_cnt = grp_start->slot_cnt;
+                               grp_iter = grp_start;
+
+                               list_for_each_entry_from(grp_iter,
+                                       &iop_chan->chain, chain_node) {
+                                       zero_sum_result |=
+                                           iop_desc_get_zero_result(grp_iter);
+                                           pr_debug("\titer%d result: %d\n",
+                                           grp_iter->idx, zero_sum_result);
+                                       slot_cnt -= slots_per_op;
+                                       if (slot_cnt == 0)
+                                               break;
+                               }
+                               pr_debug("\tgrp_start->xor_check_result: %p\n",
+                                       grp_start->xor_check_result);
+                               *grp_start->xor_check_result = zero_sum_result;
+                       }
+
+                       /* clean up the group */
+                       slot_cnt = grp_start->slot_cnt;
+                       grp_iter = grp_start;
+                       list_for_each_entry_safe_from(grp_iter, _grp_iter,
+                               &iop_chan->chain, chain_node) {
+                               cookie = iop_adma_run_tx_complete_actions(
+                                       grp_iter, iop_chan, cookie);
+
+                               slot_cnt -= slots_per_op;
+                               end_of_chain = iop_adma_clean_slot(grp_iter,
+                                       iop_chan);
+
+                               if (slot_cnt == 0 || end_of_chain)
+                                       break;
+                       }
+
+                       /* the group should be complete at this point */
+                       BUG_ON(slot_cnt);
+
+                       slots_per_op = 0;
+                       grp_start = NULL;
+                       if (end_of_chain)
+                               break;
+                       else
+                               continue;
+               } else if (slots_per_op) /* wait for group completion */
+                       continue;
+
+               /* write back zero sum results (single descriptor case) */
+               if (iter->xor_check_result && iter->async_tx.cookie)
+                       *iter->xor_check_result =
+                               iop_desc_get_zero_result(iter);
+
+               cookie = iop_adma_run_tx_complete_actions(
+                                       iter, iop_chan, cookie);
+
+               if (iop_adma_clean_slot(iter, iop_chan))
+                       break;
+       }
+
+       BUG_ON(!seen_current);
+
+       iop_chan_idle(busy, iop_chan);
+
+       if (cookie > 0) {
+               iop_chan->completed_cookie = cookie;
+               pr_debug("\tcompleted cookie %d\n", cookie);
+       }
+}
+
+static void
+iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+{
+       spin_lock_bh(&iop_chan->lock);
+       __iop_adma_slot_cleanup(iop_chan);
+       spin_unlock_bh(&iop_chan->lock);
+}
+
+static void iop_adma_tasklet(unsigned long data)
+{
+       struct iop_adma_chan *chan = (struct iop_adma_chan *) data;
+       __iop_adma_slot_cleanup(chan);
+}
+
+static struct iop_adma_desc_slot *
+iop_adma_alloc_slots(struct iop_adma_chan *iop_chan, int num_slots,
+                       int slots_per_op)
+{
+       struct iop_adma_desc_slot *iter, *_iter, *alloc_start = NULL;
+       struct list_head chain = LIST_HEAD_INIT(chain);
+       int slots_found, retry = 0;
+
+       /* start search from the last allocated descrtiptor
+        * if a contiguous allocation can not be found start searching
+        * from the beginning of the list
+        */
+retry:
+       slots_found = 0;
+       if (retry == 0)
+               iter = iop_chan->last_used;
+       else
+               iter = list_entry(&iop_chan->all_slots,
+                       struct iop_adma_desc_slot,
+                       slot_node);
+
+       list_for_each_entry_safe_continue(
+               iter, _iter, &iop_chan->all_slots, slot_node) {
+               prefetch(_iter);
+               prefetch(&_iter->async_tx);
+               if (iter->slots_per_op) {
+                       /* give up after finding the first busy slot
+                        * on the second pass through the list
+                        */
+                       if (retry)
+                               break;
+
+                       slots_found = 0;
+                       continue;
+               }
+
+               /* start the allocation if the slot is correctly aligned */
+               if (!slots_found++) {
+                       if (iop_desc_is_aligned(iter, slots_per_op))
+                               alloc_start = iter;
+                       else {
+                               slots_found = 0;
+                               continue;
+                       }
+               }
+
+               if (slots_found == num_slots) {
+                       struct iop_adma_desc_slot *alloc_tail = NULL;
+                       struct iop_adma_desc_slot *last_used = NULL;
+                       iter = alloc_start;
+                       while (num_slots) {
+                               int i;
+                               dev_dbg(iop_chan->device->common.dev,
+                                       "allocated slot: %d "
+                                       "(desc %p phys: %#x) slots_per_op %d\n",
+                                       iter->idx, iter->hw_desc,
+                                       iter->async_tx.phys, slots_per_op);
+
+                               /* pre-ack all but the last descriptor */
+                               if (num_slots != slots_per_op)
+                                       iter->async_tx.ack = 1;
+                               else
+                                       iter->async_tx.ack = 0;
+
+                               list_add_tail(&iter->chain_node, &chain);
+                               alloc_tail = iter;
+                               iter->async_tx.cookie = 0;
+                               iter->slot_cnt = num_slots;
+                               iter->xor_check_result = NULL;
+                               for (i = 0; i < slots_per_op; i++) {
+                                       iter->slots_per_op = slots_per_op - i;
+                                       last_used = iter;
+                                       iter = list_entry(iter->slot_node.next,
+                                               struct iop_adma_desc_slot,
+                                               slot_node);
+                               }
+                               num_slots -= slots_per_op;
+                       }
+                       alloc_tail->group_head = alloc_start;
+                       alloc_tail->async_tx.cookie = -EBUSY;
+                       list_splice(&chain, &alloc_tail->async_tx.tx_list);
+                       iop_chan->last_used = last_used;
+                       iop_desc_clear_next_desc(alloc_start);
+                       iop_desc_clear_next_desc(alloc_tail);
+                       return alloc_tail;
+               }
+       }
+       if (!retry++)
+               goto retry;
+
+       /* try to free some slots if the allocation fails */
+       tasklet_schedule(&iop_chan->irq_tasklet);
+
+       return NULL;
+}
+
+static dma_cookie_t
+iop_desc_assign_cookie(struct iop_adma_chan *iop_chan,
+       struct iop_adma_desc_slot *desc)
+{
+       dma_cookie_t cookie = iop_chan->common.cookie;
+       cookie++;
+       if (cookie < 0)
+               cookie = 1;
+       iop_chan->common.cookie = desc->async_tx.cookie = cookie;
+       return cookie;
+}
+
+static void iop_adma_check_threshold(struct iop_adma_chan *iop_chan)
+{
+       dev_dbg(iop_chan->device->common.dev, "pending: %d\n",
+               iop_chan->pending);
+
+       if (iop_chan->pending >= IOP_ADMA_THRESHOLD) {
+               iop_chan->pending = 0;
+               iop_chan_append(iop_chan);
+       }
+}
+
+static dma_cookie_t
+iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+       struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
+       struct iop_adma_desc_slot *grp_start, *old_chain_tail;
+       int slot_cnt;
+       int slots_per_op;
+       dma_cookie_t cookie;
+
+       grp_start = sw_desc->group_head;
+       slot_cnt = grp_start->slot_cnt;
+       slots_per_op = grp_start->slots_per_op;
+
+       spin_lock_bh(&iop_chan->lock);
+       cookie = iop_desc_assign_cookie(iop_chan, sw_desc);
+
+       old_chain_tail = list_entry(iop_chan->chain.prev,
+               struct iop_adma_desc_slot, chain_node);
+       list_splice_init(&sw_desc->async_tx.tx_list,
+                        &old_chain_tail->chain_node);
+
+       /* fix up the hardware chain */
+       iop_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys);
+
+       /* 1/ don't add pre-chained descriptors
+        * 2/ dummy read to flush next_desc write
+        */
+       BUG_ON(iop_desc_get_next_desc(sw_desc));
+
+       /* increment the pending count by the number of slots
+        * memcpy operations have a 1:1 (slot:operation) relation
+        * other operations are heavier and will pop the threshold
+        * more often.
+        */
+       iop_chan->pending += slot_cnt;
+       iop_adma_check_threshold(iop_chan);
+       spin_unlock_bh(&iop_chan->lock);
+
+       dev_dbg(iop_chan->device->common.dev, "%s cookie: %d slot: %d\n",
+               __FUNCTION__, sw_desc->async_tx.cookie, sw_desc->idx);
+
+       return cookie;
+}
+
+static void
+iop_adma_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+       int index)
+{
+       struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
+
+       /* to do: support transfers lengths > IOP_ADMA_MAX_BYTE_COUNT */
+       iop_desc_set_dest_addr(sw_desc->group_head, iop_chan, addr);
+}
+
+static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan);
+static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan);
+
+/* returns the number of allocated descriptors */
+static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
+{
+       char *hw_desc;
+       int idx;
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+       struct iop_adma_desc_slot *slot = NULL;
+       int init = iop_chan->slots_allocated ? 0 : 1;
+       struct iop_adma_platform_data *plat_data =
+               iop_chan->device->pdev->dev.platform_data;
+       int num_descs_in_pool = plat_data->pool_size/IOP_ADMA_SLOT_SIZE;
+
+       /* Allocate descriptor slots */
+       do {
+               idx = iop_chan->slots_allocated;
+               if (idx == num_descs_in_pool)
+                       break;
+
+               slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+               if (!slot) {
+                       printk(KERN_INFO "IOP ADMA Channel only initialized"
+                               " %d descriptor slots", idx);
+                       break;
+               }
+               hw_desc = (char *) iop_chan->device->dma_desc_pool_virt;
+               slot->hw_desc = (void *) &hw_desc[idx * IOP_ADMA_SLOT_SIZE];
+
+               dma_async_tx_descriptor_init(&slot->async_tx, chan);
+               slot->async_tx.tx_submit = iop_adma_tx_submit;
+               slot->async_tx.tx_set_dest = iop_adma_set_dest;
+               INIT_LIST_HEAD(&slot->chain_node);
+               INIT_LIST_HEAD(&slot->slot_node);
+               INIT_LIST_HEAD(&slot->async_tx.tx_list);
+               hw_desc = (char *) iop_chan->device->dma_desc_pool;
+               slot->async_tx.phys =
+                       (dma_addr_t) &hw_desc[idx * IOP_ADMA_SLOT_SIZE];
+               slot->idx = idx;
+
+               spin_lock_bh(&iop_chan->lock);
+               iop_chan->slots_allocated++;
+               list_add_tail(&slot->slot_node, &iop_chan->all_slots);
+               spin_unlock_bh(&iop_chan->lock);
+       } while (iop_chan->slots_allocated < num_descs_in_pool);
+
+       if (idx && !iop_chan->last_used)
+               iop_chan->last_used = list_entry(iop_chan->all_slots.next,
+                                       struct iop_adma_desc_slot,
+                                       slot_node);
+
+       dev_dbg(iop_chan->device->common.dev,
+               "allocated %d descriptor slots last_used: %p\n",
+               iop_chan->slots_allocated, iop_chan->last_used);
+
+       /* initialize the channel and the chain with a null operation */
+       if (init) {
+               if (dma_has_cap(DMA_MEMCPY,
+                       iop_chan->device->common.cap_mask))
+                       iop_chan_start_null_memcpy(iop_chan);
+               else if (dma_has_cap(DMA_XOR,
+                       iop_chan->device->common.cap_mask))
+                       iop_chan_start_null_xor(iop_chan);
+               else
+                       BUG();
+       }
+
+       return (idx > 0) ? idx : -ENOMEM;
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_interrupt(struct dma_chan *chan)
+{
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+       struct iop_adma_desc_slot *sw_desc, *grp_start;
+       int slot_cnt, slots_per_op;
+
+       dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+
+       spin_lock_bh(&iop_chan->lock);
+       slot_cnt = iop_chan_interrupt_slot_count(&slots_per_op, iop_chan);
+       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+       if (sw_desc) {
+               grp_start = sw_desc->group_head;
+               iop_desc_init_interrupt(grp_start, iop_chan);
+               grp_start->unmap_len = 0;
+       }
+       spin_unlock_bh(&iop_chan->lock);
+
+       return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void
+iop_adma_memcpy_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+       int index)
+{
+       struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+       struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+
+       iop_desc_set_memcpy_src_addr(grp_start, addr);
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_memcpy(struct dma_chan *chan, size_t len, int int_en)
+{
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+       struct iop_adma_desc_slot *sw_desc, *grp_start;
+       int slot_cnt, slots_per_op;
+
+       if (unlikely(!len))
+               return NULL;
+       BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
+
+       dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+               __FUNCTION__, len);
+
+       spin_lock_bh(&iop_chan->lock);
+       slot_cnt = iop_chan_memcpy_slot_count(len, &slots_per_op);
+       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+       if (sw_desc) {
+               grp_start = sw_desc->group_head;
+               iop_desc_init_memcpy(grp_start, int_en);
+               iop_desc_set_byte_count(grp_start, iop_chan, len);
+               sw_desc->unmap_src_cnt = 1;
+               sw_desc->unmap_len = len;
+               sw_desc->async_tx.tx_set_src = iop_adma_memcpy_set_src;
+       }
+       spin_unlock_bh(&iop_chan->lock);
+
+       return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_memset(struct dma_chan *chan, int value, size_t len,
+       int int_en)
+{
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+       struct iop_adma_desc_slot *sw_desc, *grp_start;
+       int slot_cnt, slots_per_op;
+
+       if (unlikely(!len))
+               return NULL;
+       BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
+
+       dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+               __FUNCTION__, len);
+
+       spin_lock_bh(&iop_chan->lock);
+       slot_cnt = iop_chan_memset_slot_count(len, &slots_per_op);
+       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+       if (sw_desc) {
+               grp_start = sw_desc->group_head;
+               iop_desc_init_memset(grp_start, int_en);
+               iop_desc_set_byte_count(grp_start, iop_chan, len);
+               iop_desc_set_block_fill_val(grp_start, value);
+               sw_desc->unmap_src_cnt = 1;
+               sw_desc->unmap_len = len;
+       }
+       spin_unlock_bh(&iop_chan->lock);
+
+       return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void
+iop_adma_xor_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+       int index)
+{
+       struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+       struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+
+       iop_desc_set_xor_src_addr(grp_start, index, addr);
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_xor(struct dma_chan *chan, unsigned int src_cnt, size_t len,
+       int int_en)
+{
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+       struct iop_adma_desc_slot *sw_desc, *grp_start;
+       int slot_cnt, slots_per_op;
+
+       if (unlikely(!len))
+               return NULL;
+       BUG_ON(unlikely(len > IOP_ADMA_XOR_MAX_BYTE_COUNT));
+
+       dev_dbg(iop_chan->device->common.dev,
+               "%s src_cnt: %d len: %u int_en: %d\n",
+               __FUNCTION__, src_cnt, len, int_en);
+
+       spin_lock_bh(&iop_chan->lock);
+       slot_cnt = iop_chan_xor_slot_count(len, src_cnt, &slots_per_op);
+       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+       if (sw_desc) {
+               grp_start = sw_desc->group_head;
+               iop_desc_init_xor(grp_start, src_cnt, int_en);
+               iop_desc_set_byte_count(grp_start, iop_chan, len);
+               sw_desc->unmap_src_cnt = src_cnt;
+               sw_desc->unmap_len = len;
+               sw_desc->async_tx.tx_set_src = iop_adma_xor_set_src;
+       }
+       spin_unlock_bh(&iop_chan->lock);
+
+       return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void
+iop_adma_xor_zero_sum_set_src(dma_addr_t addr,
+                               struct dma_async_tx_descriptor *tx,
+                               int index)
+{
+       struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+       struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+
+       iop_desc_set_zero_sum_src_addr(grp_start, index, addr);
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_zero_sum(struct dma_chan *chan, unsigned int src_cnt,
+       size_t len, u32 *result, int int_en)
+{
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+       struct iop_adma_desc_slot *sw_desc, *grp_start;
+       int slot_cnt, slots_per_op;
+
+       if (unlikely(!len))
+               return NULL;
+
+       dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %u\n",
+               __FUNCTION__, src_cnt, len);
+
+       spin_lock_bh(&iop_chan->lock);
+       slot_cnt = iop_chan_zero_sum_slot_count(len, src_cnt, &slots_per_op);
+       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+       if (sw_desc) {
+               grp_start = sw_desc->group_head;
+               iop_desc_init_zero_sum(grp_start, src_cnt, int_en);
+               iop_desc_set_zero_sum_byte_count(grp_start, len);
+               grp_start->xor_check_result = result;
+               pr_debug("\t%s: grp_start->xor_check_result: %p\n",
+                       __FUNCTION__, grp_start->xor_check_result);
+               sw_desc->unmap_src_cnt = src_cnt;
+               sw_desc->unmap_len = len;
+               sw_desc->async_tx.tx_set_src = iop_adma_xor_zero_sum_set_src;
+       }
+       spin_unlock_bh(&iop_chan->lock);
+
+       return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void iop_adma_dependency_added(struct dma_chan *chan)
+{
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+       tasklet_schedule(&iop_chan->irq_tasklet);
+}
+
+static void iop_adma_free_chan_resources(struct dma_chan *chan)
+{
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+       struct iop_adma_desc_slot *iter, *_iter;
+       int in_use_descs = 0;
+
+       iop_adma_slot_cleanup(iop_chan);
+
+       spin_lock_bh(&iop_chan->lock);
+       list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
+                                       chain_node) {
+               in_use_descs++;
+               list_del(&iter->chain_node);
+       }
+       list_for_each_entry_safe_reverse(
+               iter, _iter, &iop_chan->all_slots, slot_node) {
+               list_del(&iter->slot_node);
+               kfree(iter);
+               iop_chan->slots_allocated--;
+       }
+       iop_chan->last_used = NULL;
+
+       dev_dbg(iop_chan->device->common.dev, "%s slots_allocated %d\n",
+               __FUNCTION__, iop_chan->slots_allocated);
+       spin_unlock_bh(&iop_chan->lock);
+
+       /* one is ok since we left it on there on purpose */
+       if (in_use_descs > 1)
+               printk(KERN_ERR "IOP: Freeing %d in use descriptors!\n",
+                       in_use_descs - 1);
+}
+
+/**
+ * iop_adma_is_complete - poll the status of an ADMA transaction
+ * @chan: ADMA channel handle
+ * @cookie: ADMA transaction identifier
+ */
+static enum dma_status iop_adma_is_complete(struct dma_chan *chan,
+                                       dma_cookie_t cookie,
+                                       dma_cookie_t *done,
+                                       dma_cookie_t *used)
+{
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+       dma_cookie_t last_used;
+       dma_cookie_t last_complete;
+       enum dma_status ret;
+
+       last_used = chan->cookie;
+       last_complete = iop_chan->completed_cookie;
+
+       if (done)
+               *done = last_complete;
+       if (used)
+               *used = last_used;
+
+       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       if (ret == DMA_SUCCESS)
+               return ret;
+
+       iop_adma_slot_cleanup(iop_chan);
+
+       last_used = chan->cookie;
+       last_complete = iop_chan->completed_cookie;
+
+       if (done)
+               *done = last_complete;
+       if (used)
+               *used = last_used;
+
+       return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+static irqreturn_t iop_adma_eot_handler(int irq, void *data)
+{
+       struct iop_adma_chan *chan = data;
+
+       dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
+
+       tasklet_schedule(&chan->irq_tasklet);
+
+       iop_adma_device_clear_eot_status(chan);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t iop_adma_eoc_handler(int irq, void *data)
+{
+       struct iop_adma_chan *chan = data;
+
+       dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
+
+       tasklet_schedule(&chan->irq_tasklet);
+
+       iop_adma_device_clear_eoc_status(chan);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t iop_adma_err_handler(int irq, void *data)
+{
+       struct iop_adma_chan *chan = data;
+       unsigned long status = iop_chan_get_status(chan);
+
+       dev_printk(KERN_ERR, chan->device->common.dev,
+               "error ( %s%s%s%s%s%s%s)\n",
+               iop_is_err_int_parity(status, chan) ? "int_parity " : "",
+               iop_is_err_mcu_abort(status, chan) ? "mcu_abort " : "",
+               iop_is_err_int_tabort(status, chan) ? "int_tabort " : "",
+               iop_is_err_int_mabort(status, chan) ? "int_mabort " : "",
+               iop_is_err_pci_tabort(status, chan) ? "pci_tabort " : "",
+               iop_is_err_pci_mabort(status, chan) ? "pci_mabort " : "",
+               iop_is_err_split_tx(status, chan) ? "split_tx " : "");
+
+       iop_adma_device_clear_err_status(chan);
+
+       BUG();
+
+       return IRQ_HANDLED;
+}
+
+static void iop_adma_issue_pending(struct dma_chan *chan)
+{
+       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+
+       if (iop_chan->pending) {
+               iop_chan->pending = 0;
+               iop_chan_append(iop_chan);
+       }
+}
+
+/*
+ * Perform a transaction to verify the HW works.
+ */
+#define IOP_ADMA_TEST_SIZE 2000
+
+static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
+{
+       int i;
+       void *src, *dest;
+       dma_addr_t src_dma, dest_dma;
+       struct dma_chan *dma_chan;
+       dma_cookie_t cookie;
+       struct dma_async_tx_descriptor *tx;
+       int err = 0;
+       struct iop_adma_chan *iop_chan;
+
+       dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
+
+       src = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
+       if (!src)
+               return -ENOMEM;
+       dest = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
+       if (!dest) {
+               kfree(src);
+               return -ENOMEM;
+       }
+
+       /* Fill in src buffer */
+       for (i = 0; i < IOP_ADMA_TEST_SIZE; i++)
+               ((u8 *) src)[i] = (u8)i;
+
+       memset(dest, 0, IOP_ADMA_TEST_SIZE);
+
+       /* Start copy, using first DMA channel */
+       dma_chan = container_of(device->common.channels.next,
+                               struct dma_chan,
+                               device_node);
+       if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+               err = -ENODEV;
+               goto out;
+       }
+
+       tx = iop_adma_prep_dma_memcpy(dma_chan, IOP_ADMA_TEST_SIZE, 1);
+       dest_dma = dma_map_single(dma_chan->device->dev, dest,
+                               IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
+       iop_adma_set_dest(dest_dma, tx, 0);
+       src_dma = dma_map_single(dma_chan->device->dev, src,
+                               IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE);
+       iop_adma_memcpy_set_src(src_dma, tx, 0);
+
+       cookie = iop_adma_tx_submit(tx);
+       iop_adma_issue_pending(dma_chan);
+       async_tx_ack(tx);
+       msleep(1);
+
+       if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+                       DMA_SUCCESS) {
+               dev_printk(KERN_ERR, dma_chan->device->dev,
+                       "Self-test copy timed out, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+
+       iop_chan = to_iop_adma_chan(dma_chan);
+       dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
+               IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
+       if (memcmp(src, dest, IOP_ADMA_TEST_SIZE)) {
+               dev_printk(KERN_ERR, dma_chan->device->dev,
+                       "Self-test copy failed compare, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+
+free_resources:
+       iop_adma_free_chan_resources(dma_chan);
+out:
+       kfree(src);
+       kfree(dest);
+       return err;
+}
+
+#define IOP_ADMA_NUM_SRC_TEST 4 /* must be <= 15 */
+static int __devinit
+iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+{
+       int i, src_idx;
+       struct page *dest;
+       struct page *xor_srcs[IOP_ADMA_NUM_SRC_TEST];
+       struct page *zero_sum_srcs[IOP_ADMA_NUM_SRC_TEST + 1];
+       dma_addr_t dma_addr, dest_dma;
+       struct dma_async_tx_descriptor *tx;
+       struct dma_chan *dma_chan;
+       dma_cookie_t cookie;
+       u8 cmp_byte = 0;
+       u32 cmp_word;
+       u32 zero_sum_result;
+       int err = 0;
+       struct iop_adma_chan *iop_chan;
+
+       dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
+
+       for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
+               xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
+               if (!xor_srcs[src_idx])
+                       while (src_idx--) {
+                               __free_page(xor_srcs[src_idx]);
+                               return -ENOMEM;
+                       }
+       }
+
+       dest = alloc_page(GFP_KERNEL);
+       if (!dest)
+               while (src_idx--) {
+                       __free_page(xor_srcs[src_idx]);
+                       return -ENOMEM;
+               }
+
+       /* Fill in src buffers */
+       for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
+               u8 *ptr = page_address(xor_srcs[src_idx]);
+               for (i = 0; i < PAGE_SIZE; i++)
+                       ptr[i] = (1 << src_idx);
+       }
+
+       for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++)
+               cmp_byte ^= (u8) (1 << src_idx);
+
+       cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
+                       (cmp_byte << 8) | cmp_byte;
+
+       memset(page_address(dest), 0, PAGE_SIZE);
+
+       dma_chan = container_of(device->common.channels.next,
+                               struct dma_chan,
+                               device_node);
+       if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+               err = -ENODEV;
+               goto out;
+       }
+
+       /* test xor */
+       tx = iop_adma_prep_dma_xor(dma_chan, IOP_ADMA_NUM_SRC_TEST,
+                               PAGE_SIZE, 1);
+       dest_dma = dma_map_page(dma_chan->device->dev, dest, 0,
+                               PAGE_SIZE, DMA_FROM_DEVICE);
+       iop_adma_set_dest(dest_dma, tx, 0);
+
+       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) {
+               dma_addr = dma_map_page(dma_chan->device->dev, xor_srcs[i], 0,
+                       PAGE_SIZE, DMA_TO_DEVICE);
+               iop_adma_xor_set_src(dma_addr, tx, i);
+       }
+
+       cookie = iop_adma_tx_submit(tx);
+       iop_adma_issue_pending(dma_chan);
+       async_tx_ack(tx);
+       msleep(8);
+
+       if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+               DMA_SUCCESS) {
+               dev_printk(KERN_ERR, dma_chan->device->dev,
+                       "Self-test xor timed out, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+
+       iop_chan = to_iop_adma_chan(dma_chan);
+       dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
+               PAGE_SIZE, DMA_FROM_DEVICE);
+       for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
+               u32 *ptr = page_address(dest);
+               if (ptr[i] != cmp_word) {
+                       dev_printk(KERN_ERR, dma_chan->device->dev,
+                               "Self-test xor failed compare, disabling\n");
+                       err = -ENODEV;
+                       goto free_resources;
+               }
+       }
+       dma_sync_single_for_device(&iop_chan->device->pdev->dev, dest_dma,
+               PAGE_SIZE, DMA_TO_DEVICE);
+
+       /* skip zero sum if the capability is not present */
+       if (!dma_has_cap(DMA_ZERO_SUM, dma_chan->device->cap_mask))
+               goto free_resources;
+
+       /* zero sum the sources with the destintation page */
+       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++)
+               zero_sum_srcs[i] = xor_srcs[i];
+       zero_sum_srcs[i] = dest;
+
+       zero_sum_result = 1;
+
+       tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
+               PAGE_SIZE, &zero_sum_result, 1);
+       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
+               dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
+                       0, PAGE_SIZE, DMA_TO_DEVICE);
+               iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
+       }
+
+       cookie = iop_adma_tx_submit(tx);
+       iop_adma_issue_pending(dma_chan);
+       async_tx_ack(tx);
+       msleep(8);
+
+       if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+               dev_printk(KERN_ERR, dma_chan->device->dev,
+                       "Self-test zero sum timed out, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+
+       if (zero_sum_result != 0) {
+               dev_printk(KERN_ERR, dma_chan->device->dev,
+                       "Self-test zero sum failed compare, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+
+       /* test memset */
+       tx = iop_adma_prep_dma_memset(dma_chan, 0, PAGE_SIZE, 1);
+       dma_addr = dma_map_page(dma_chan->device->dev, dest, 0,
+                       PAGE_SIZE, DMA_FROM_DEVICE);
+       iop_adma_set_dest(dma_addr, tx, 0);
+
+       cookie = iop_adma_tx_submit(tx);
+       iop_adma_issue_pending(dma_chan);
+       async_tx_ack(tx);
+       msleep(8);
+
+       if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+               dev_printk(KERN_ERR, dma_chan->device->dev,
+                       "Self-test memset timed out, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+
+       for (i = 0; i < PAGE_SIZE/sizeof(u32); i++) {
+               u32 *ptr = page_address(dest);
+               if (ptr[i]) {
+                       dev_printk(KERN_ERR, dma_chan->device->dev,
+                               "Self-test memset failed compare, disabling\n");
+                       err = -ENODEV;
+                       goto free_resources;
+               }
+       }
+
+       /* test for non-zero parity sum */
+       zero_sum_result = 0;
+       tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
+               PAGE_SIZE, &zero_sum_result, 1);
+       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
+               dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
+                       0, PAGE_SIZE, DMA_TO_DEVICE);
+               iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
+       }
+
+       cookie = iop_adma_tx_submit(tx);
+       iop_adma_issue_pending(dma_chan);
+       async_tx_ack(tx);
+       msleep(8);
+
+       if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+               dev_printk(KERN_ERR, dma_chan->device->dev,
+                       "Self-test non-zero sum timed out, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+
+       if (zero_sum_result != 1) {
+               dev_printk(KERN_ERR, dma_chan->device->dev,
+                       "Self-test non-zero sum failed compare, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+
+free_resources:
+       iop_adma_free_chan_resources(dma_chan);
+out:
+       src_idx = IOP_ADMA_NUM_SRC_TEST;
+       while (src_idx--)
+               __free_page(xor_srcs[src_idx]);
+       __free_page(dest);
+       return err;
+}
+
+static int __devexit iop_adma_remove(struct platform_device *dev)
+{
+       struct iop_adma_device *device = platform_get_drvdata(dev);
+       struct dma_chan *chan, *_chan;
+       struct iop_adma_chan *iop_chan;
+       int i;
+       struct iop_adma_platform_data *plat_data = dev->dev.platform_data;
+
+       dma_async_device_unregister(&device->common);
+
+       for (i = 0; i < 3; i++) {
+               unsigned int irq;
+               irq = platform_get_irq(dev, i);
+               free_irq(irq, device);
+       }
+
+       dma_free_coherent(&dev->dev, plat_data->pool_size,
+                       device->dma_desc_pool_virt, device->dma_desc_pool);
+
+       do {
+               struct resource *res;
+               res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+               release_mem_region(res->start, res->end - res->start);
+       } while (0);
+
+       list_for_each_entry_safe(chan, _chan, &device->common.channels,
+                               device_node) {
+               iop_chan = to_iop_adma_chan(chan);
+               list_del(&chan->device_node);
+               kfree(iop_chan);
+       }
+       kfree(device);
+
+       return 0;
+}
+
+static int __devinit iop_adma_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       int ret = 0, i;
+       struct iop_adma_device *adev;
+       struct iop_adma_chan *iop_chan;
+       struct dma_device *dma_dev;
+       struct iop_adma_platform_data *plat_data = pdev->dev.platform_data;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+
+       if (!devm_request_mem_region(&pdev->dev, res->start,
+                               res->end - res->start, pdev->name))
+               return -EBUSY;
+
+       adev = kzalloc(sizeof(*adev), GFP_KERNEL);
+       if (!adev)
+               return -ENOMEM;
+       dma_dev = &adev->common;
+
+       /* allocate coherent memory for hardware descriptors
+        * note: writecombine gives slightly better performance, but
+        * requires that we explicitly flush the writes
+        */
+       if ((adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
+                                       plat_data->pool_size,
+                                       &adev->dma_desc_pool,
+                                       GFP_KERNEL)) == NULL) {
+               ret = -ENOMEM;
+               goto err_free_adev;
+       }
+
+       dev_dbg(&pdev->dev, "%s: allocted descriptor pool virt %p phys %p\n",
+               __FUNCTION__, adev->dma_desc_pool_virt,
+               (void *) adev->dma_desc_pool);
+
+       adev->id = plat_data->hw_id;
+
+       /* discover transaction capabilites from the platform data */
+       dma_dev->cap_mask = plat_data->cap_mask;
+
+       adev->pdev = pdev;
+       platform_set_drvdata(pdev, adev);
+
+       INIT_LIST_HEAD(&dma_dev->channels);
+
+       /* set base routines */
+       dma_dev->device_alloc_chan_resources = iop_adma_alloc_chan_resources;
+       dma_dev->device_free_chan_resources = iop_adma_free_chan_resources;
+       dma_dev->device_is_tx_complete = iop_adma_is_complete;
+       dma_dev->device_issue_pending = iop_adma_issue_pending;
+       dma_dev->device_dependency_added = iop_adma_dependency_added;
+       dma_dev->dev = &pdev->dev;
+
+       /* set prep routines based on capability */
+       if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask))
+               dma_dev->device_prep_dma_memcpy = iop_adma_prep_dma_memcpy;
+       if (dma_has_cap(DMA_MEMSET, dma_dev->cap_mask))
+               dma_dev->device_prep_dma_memset = iop_adma_prep_dma_memset;
+       if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+               dma_dev->max_xor = iop_adma_get_max_xor();
+               dma_dev->device_prep_dma_xor = iop_adma_prep_dma_xor;
+       }
+       if (dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask))
+               dma_dev->device_prep_dma_zero_sum =
+                       iop_adma_prep_dma_zero_sum;
+       if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask))
+               dma_dev->device_prep_dma_interrupt =
+                       iop_adma_prep_dma_interrupt;
+
+       iop_chan = kzalloc(sizeof(*iop_chan), GFP_KERNEL);
+       if (!iop_chan) {
+               ret = -ENOMEM;
+               goto err_free_dma;
+       }
+       iop_chan->device = adev;
+
+       iop_chan->mmr_base = devm_ioremap(&pdev->dev, res->start,
+                                       res->end - res->start);
+       if (!iop_chan->mmr_base) {
+               ret = -ENOMEM;
+               goto err_free_iop_chan;
+       }
+       tasklet_init(&iop_chan->irq_tasklet, iop_adma_tasklet, (unsigned long)
+               iop_chan);
+
+       /* clear errors before enabling interrupts */
+       iop_adma_device_clear_err_status(iop_chan);
+
+       for (i = 0; i < 3; i++) {
+               irq_handler_t handler[] = { iop_adma_eot_handler,
+                                       iop_adma_eoc_handler,
+                                       iop_adma_err_handler };
+               int irq = platform_get_irq(pdev, i);
+               if (irq < 0) {
+                       ret = -ENXIO;
+                       goto err_free_iop_chan;
+               } else {
+                       ret = devm_request_irq(&pdev->dev, irq,
+                                       handler[i], 0, pdev->name, iop_chan);
+                       if (ret)
+                               goto err_free_iop_chan;
+               }
+       }
+
+       spin_lock_init(&iop_chan->lock);
+       init_timer(&iop_chan->cleanup_watchdog);
+       iop_chan->cleanup_watchdog.data = (unsigned long) iop_chan;
+       iop_chan->cleanup_watchdog.function = iop_adma_tasklet;
+       INIT_LIST_HEAD(&iop_chan->chain);
+       INIT_LIST_HEAD(&iop_chan->all_slots);
+       INIT_RCU_HEAD(&iop_chan->common.rcu);
+       iop_chan->common.device = dma_dev;
+       list_add_tail(&iop_chan->common.device_node, &dma_dev->channels);
+
+       if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
+               ret = iop_adma_memcpy_self_test(adev);
+               dev_dbg(&pdev->dev, "memcpy self test returned %d\n", ret);
+               if (ret)
+                       goto err_free_iop_chan;
+       }
+
+       if (dma_has_cap(DMA_XOR, dma_dev->cap_mask) ||
+               dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) {
+               ret = iop_adma_xor_zero_sum_self_test(adev);
+               dev_dbg(&pdev->dev, "xor self test returned %d\n", ret);
+               if (ret)
+                       goto err_free_iop_chan;
+       }
+
+       dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: "
+         "( %s%s%s%s%s%s%s%s%s%s)\n",
+         dma_has_cap(DMA_PQ_XOR, dma_dev->cap_mask) ? "pq_xor " : "",
+         dma_has_cap(DMA_PQ_UPDATE, dma_dev->cap_mask) ? "pq_update " : "",
+         dma_has_cap(DMA_PQ_ZERO_SUM, dma_dev->cap_mask) ? "pq_zero_sum " : "",
+         dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
+         dma_has_cap(DMA_DUAL_XOR, dma_dev->cap_mask) ? "dual_xor " : "",
+         dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask) ? "xor_zero_sum " : "",
+         dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)  ? "fill " : "",
+         dma_has_cap(DMA_MEMCPY_CRC32C, dma_dev->cap_mask) ? "cpy+crc " : "",
+         dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
+         dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
+
+       dma_async_device_register(dma_dev);
+       goto out;
+
+ err_free_iop_chan:
+       kfree(iop_chan);
+ err_free_dma:
+       dma_free_coherent(&adev->pdev->dev, plat_data->pool_size,
+                       adev->dma_desc_pool_virt, adev->dma_desc_pool);
+ err_free_adev:
+       kfree(adev);
+ out:
+       return ret;
+}
+
+static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
+{
+       struct iop_adma_desc_slot *sw_desc, *grp_start;
+       dma_cookie_t cookie;
+       int slot_cnt, slots_per_op;
+
+       dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+
+       spin_lock_bh(&iop_chan->lock);
+       slot_cnt = iop_chan_memcpy_slot_count(0, &slots_per_op);
+       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+       if (sw_desc) {
+               grp_start = sw_desc->group_head;
+
+               list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+               sw_desc->async_tx.ack = 1;
+               iop_desc_init_memcpy(grp_start, 0);
+               iop_desc_set_byte_count(grp_start, iop_chan, 0);
+               iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+               iop_desc_set_memcpy_src_addr(grp_start, 0);
+
+               cookie = iop_chan->common.cookie;
+               cookie++;
+               if (cookie <= 1)
+                       cookie = 2;
+
+               /* initialize the completed cookie to be less than
+                * the most recently used cookie
+                */
+               iop_chan->completed_cookie = cookie - 1;
+               iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+
+               /* channel should not be busy */
+               BUG_ON(iop_chan_is_busy(iop_chan));
+
+               /* clear any prior error-status bits */
+               iop_adma_device_clear_err_status(iop_chan);
+
+               /* disable operation */
+               iop_chan_disable(iop_chan);
+
+               /* set the descriptor address */
+               iop_chan_set_next_descriptor(iop_chan, sw_desc->async_tx.phys);
+
+               /* 1/ don't add pre-chained descriptors
+                * 2/ dummy read to flush next_desc write
+                */
+               BUG_ON(iop_desc_get_next_desc(sw_desc));
+
+               /* run the descriptor */
+               iop_chan_enable(iop_chan);
+       } else
+               dev_printk(KERN_ERR, iop_chan->device->common.dev,
+                        "failed to allocate null descriptor\n");
+       spin_unlock_bh(&iop_chan->lock);
+}
+
+static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
+{
+       struct iop_adma_desc_slot *sw_desc, *grp_start;
+       dma_cookie_t cookie;
+       int slot_cnt, slots_per_op;
+
+       dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+
+       spin_lock_bh(&iop_chan->lock);
+       slot_cnt = iop_chan_xor_slot_count(0, 2, &slots_per_op);
+       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+       if (sw_desc) {
+               grp_start = sw_desc->group_head;
+               list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+               sw_desc->async_tx.ack = 1;
+               iop_desc_init_null_xor(grp_start, 2, 0);
+               iop_desc_set_byte_count(grp_start, iop_chan, 0);
+               iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+               iop_desc_set_xor_src_addr(grp_start, 0, 0);
+               iop_desc_set_xor_src_addr(grp_start, 1, 0);
+
+               cookie = iop_chan->common.cookie;
+               cookie++;
+               if (cookie <= 1)
+                       cookie = 2;
+
+               /* initialize the completed cookie to be less than
+                * the most recently used cookie
+                */
+               iop_chan->completed_cookie = cookie - 1;
+               iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+
+               /* channel should not be busy */
+               BUG_ON(iop_chan_is_busy(iop_chan));
+
+               /* clear any prior error-status bits */
+               iop_adma_device_clear_err_status(iop_chan);
+
+               /* disable operation */
+               iop_chan_disable(iop_chan);
+
+               /* set the descriptor address */
+               iop_chan_set_next_descriptor(iop_chan, sw_desc->async_tx.phys);
+
+               /* 1/ don't add pre-chained descriptors
+                * 2/ dummy read to flush next_desc write
+                */
+               BUG_ON(iop_desc_get_next_desc(sw_desc));
+
+               /* run the descriptor */
+               iop_chan_enable(iop_chan);
+       } else
+               dev_printk(KERN_ERR, iop_chan->device->common.dev,
+                       "failed to allocate null descriptor\n");
+       spin_unlock_bh(&iop_chan->lock);
+}
+
+static struct platform_driver iop_adma_driver = {
+       .probe          = iop_adma_probe,
+       .remove         = iop_adma_remove,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "iop-adma",
+       },
+};
+
+static int __init iop_adma_init (void)
+{
+       /* it's currently unsafe to unload this module */
+       /* if forced, worst case is that rmmod hangs */
+       __unsafe(THIS_MODULE);
+
+       return platform_driver_register(&iop_adma_driver);
+}
+
+static void __exit iop_adma_exit (void)
+{
+       platform_driver_unregister(&iop_adma_driver);
+       return;
+}
+
+module_init(iop_adma_init);
+module_exit(iop_adma_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("IOP ADMA Engine Driver");
+MODULE_LICENSE("GPL");
index 88f462122a30fea0c4516de34891fcb433538182..05f02a326f1c6283277964f307873df9cb5a5489 100644 (file)
@@ -84,4 +84,13 @@ config DCDBAS
          Say Y or M here to enable the driver for use by Dell systems
          management software such as Dell OpenManage.
 
+config DMIID
+    bool "Export DMI identification via sysfs to userspace"
+    depends on DMI
+    default y
+       help
+         Say Y here if you want to query SMBIOS/DMI system identification
+         information from userspace through /sys/class/dmi/id/ or if you want
+         DMI-based module auto-loading.
+
 endmenu
index 98e395f4bb29e8a37233f737f72fa5564208843d..8d4ebc805a505cae9ff188fc24604e88e058be60 100644 (file)
@@ -7,3 +7,4 @@ obj-$(CONFIG_EFI_VARS)          += efivars.o
 obj-$(CONFIG_EFI_PCDP)         += pcdp.o
 obj-$(CONFIG_DELL_RBU)          += dell_rbu.o
 obj-$(CONFIG_DCDBAS)           += dcdbas.o
+obj-$(CONFIG_DMIID)            += dmi-id.o
index 1865b56fb141643878b50b4874c4be56f612ff0c..18cdcb3ae1ca3d11131b0cf9498086a25066ec14 100644 (file)
@@ -149,8 +149,9 @@ static ssize_t smi_data_buf_size_store(struct device *dev,
        return count;
 }
 
-static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos,
-                            size_t count)
+static ssize_t smi_data_read(struct kobject *kobj,
+                            struct bin_attribute *bin_attr,
+                            char *buf, loff_t pos, size_t count)
 {
        size_t max_read;
        ssize_t ret;
@@ -170,8 +171,9 @@ out:
        return ret;
 }
 
-static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos,
-                             size_t count)
+static ssize_t smi_data_write(struct kobject *kobj,
+                             struct bin_attribute *bin_attr,
+                             char *buf, loff_t pos, size_t count)
 {
        ssize_t ret;
 
index 58a85182b3e8d589d704000a25cfc5ecfab23351..dcdba0f1b32c835cdcd37d0d2cb975442ab31348 100644 (file)
@@ -67,8 +67,7 @@
 #define DCDBAS_BIN_ATTR_RW(_name) \
 struct bin_attribute bin_attr_##_name = { \
        .attr =  { .name = __stringify(_name), \
-                  .mode = 0600, \
-                  .owner = THIS_MODULE }, \
+                  .mode = 0600 }, \
        .read =  _name##_read, \
        .write = _name##_write, \
 }
index fc702e40bd431c2cfdd715beacd636fb3d886c49..477a3d0e3caf83ccffb2cf472375cafcc799733e 100644 (file)
@@ -543,8 +543,9 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
        return ret_count;
 }
 
-static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
-       loff_t pos, size_t count)
+static ssize_t read_rbu_data(struct kobject *kobj,
+                            struct bin_attribute *bin_attr,
+                            char *buffer, loff_t pos, size_t count)
 {
        ssize_t ret_count = 0;
 
@@ -591,8 +592,9 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
        spin_unlock(&rbu_data.lock);
 }
 
-static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
-       loff_t pos, size_t count)
+static ssize_t read_rbu_image_type(struct kobject *kobj,
+                                  struct bin_attribute *bin_attr,
+                                  char *buffer, loff_t pos, size_t count)
 {
        int size = 0;
        if (!pos)
@@ -600,8 +602,9 @@ static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
        return size;
 }
 
-static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
-       loff_t pos, size_t count)
+static ssize_t write_rbu_image_type(struct kobject *kobj,
+                                   struct bin_attribute *bin_attr,
+                                   char *buffer, loff_t pos, size_t count)
 {
        int rc = count;
        int req_firm_rc = 0;
@@ -660,8 +663,9 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
        return rc;
 }
 
-static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
-       loff_t pos, size_t count)
+static ssize_t read_rbu_packet_size(struct kobject *kobj,
+                                   struct bin_attribute *bin_attr,
+                                   char *buffer, loff_t pos, size_t count)
 {
        int size = 0;
        if (!pos) {
@@ -672,8 +676,9 @@ static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
        return size;
 }
 
-static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
-       loff_t pos, size_t count)
+static ssize_t write_rbu_packet_size(struct kobject *kobj,
+                                    struct bin_attribute *bin_attr,
+                                    char *buffer, loff_t pos, size_t count)
 {
        unsigned long temp;
        spin_lock(&rbu_data.lock);
@@ -687,18 +692,18 @@ static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
 }
 
 static struct bin_attribute rbu_data_attr = {
-       .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
+       .attr = {.name = "data", .mode = 0444},
        .read = read_rbu_data,
 };
 
 static struct bin_attribute rbu_image_type_attr = {
-       .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
+       .attr = {.name = "image_type", .mode = 0644},
        .read = read_rbu_image_type,
        .write = write_rbu_image_type,
 };
 
 static struct bin_attribute rbu_packet_size_attr = {
-       .attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644},
+       .attr = {.name = "packet_size", .mode = 0644},
        .read = read_rbu_packet_size,
        .write = write_rbu_packet_size,
 };
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c
new file mode 100644 (file)
index 0000000..59c3b5a
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Export SMBIOS/DMI info via sysfs to userspace
+ *
+ * Copyright 2007, Lennart Poettering
+ *
+ * Licensed under GPLv2
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <linux/device.h>
+#include <linux/autoconf.h>
+
+#define DEFINE_DMI_ATTR(_name, _mode, _show)           \
+static struct device_attribute sys_dmi_##_name##_attr =        \
+       __ATTR(_name, _mode, _show, NULL);
+
+#define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field)                        \
+static ssize_t sys_dmi_##_name##_show(struct device *dev,              \
+                                     struct device_attribute *attr,    \
+                                     char *page)                       \
+{                                                                      \
+       ssize_t len;                                                    \
+       len = scnprintf(page, PAGE_SIZE, "%s\n", dmi_get_system_info(_field)); \
+       page[len-1] = '\n';                                             \
+       return len;                                                     \
+}                                                                      \
+DEFINE_DMI_ATTR(_name, _mode, sys_dmi_##_name##_show);
+
+DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor,         0444, DMI_BIOS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(bios_version,                0444, DMI_BIOS_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(bios_date,           0444, DMI_BIOS_DATE);
+DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor,          0444, DMI_SYS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(product_name,                0444, DMI_PRODUCT_NAME);
+DEFINE_DMI_ATTR_WITH_SHOW(product_version,     0444, DMI_PRODUCT_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(product_serial,      0400, DMI_PRODUCT_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(product_uuid,                0400, DMI_PRODUCT_UUID);
+DEFINE_DMI_ATTR_WITH_SHOW(board_vendor,                0444, DMI_BOARD_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(board_name,          0444, DMI_BOARD_NAME);
+DEFINE_DMI_ATTR_WITH_SHOW(board_version,       0444, DMI_BOARD_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(board_serial,                0400, DMI_BOARD_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(board_asset_tag,     0444, DMI_BOARD_ASSET_TAG);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_vendor,      0444, DMI_CHASSIS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_type,                0444, DMI_CHASSIS_TYPE);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_version,     0444, DMI_CHASSIS_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial,      0400, DMI_CHASSIS_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag,   0444, DMI_CHASSIS_ASSET_TAG);
+
+static void ascii_filter(char *d, const char *s)
+{
+       /* Filter out characters we don't want to see in the modalias string */
+       for (; *s; s++)
+               if (*s > ' ' && *s < 127 && *s != ':')
+                       *(d++) = *s;
+
+       *d = 0;
+}
+
+static ssize_t get_modalias(char *buffer, size_t buffer_size)
+{
+       static const struct mafield {
+               const char *prefix;
+               int field;
+       } fields[] = {
+               { "bvn", DMI_BIOS_VENDOR },
+               { "bvr", DMI_BIOS_VERSION },
+               { "bd",  DMI_BIOS_DATE },
+               { "svn", DMI_SYS_VENDOR },
+               { "pn",  DMI_PRODUCT_NAME },
+               { "pvr", DMI_PRODUCT_VERSION },
+               { "rvn", DMI_BOARD_VENDOR },
+               { "rn",  DMI_BOARD_NAME },
+               { "rvr", DMI_BOARD_VERSION },
+               { "cvn", DMI_CHASSIS_VENDOR },
+               { "ct",  DMI_CHASSIS_TYPE },
+               { "cvr", DMI_CHASSIS_VERSION },
+               { NULL,  DMI_NONE }
+       };
+
+       ssize_t l, left;
+       char *p;
+       const struct mafield *f;
+
+       strcpy(buffer, "dmi");
+       p = buffer + 3; left = buffer_size - 4;
+
+       for (f = fields; f->prefix && left > 0; f++) {
+               const char *c;
+               char *t;
+
+               c = dmi_get_system_info(f->field);
+               if (!c)
+                       continue;
+
+               t = kmalloc(strlen(c) + 1, GFP_KERNEL);
+               if (!t)
+                       break;
+               ascii_filter(t, c);
+               l = scnprintf(p, left, ":%s%s", f->prefix, t);
+               kfree(t);
+
+               p += l;
+               left -= l;
+       }
+
+       p[0] = ':';
+       p[1] = 0;
+
+       return p - buffer + 1;
+}
+
+static ssize_t sys_dmi_modalias_show(struct device *dev,
+                                    struct device_attribute *attr, char *page)
+{
+       ssize_t r;
+       r = get_modalias(page, PAGE_SIZE-1);
+       page[r] = '\n';
+       page[r+1] = 0;
+       return r+1;
+}
+
+DEFINE_DMI_ATTR(modalias, 0444, sys_dmi_modalias_show);
+
+static struct attribute *sys_dmi_attributes[DMI_STRING_MAX+2];
+
+static struct attribute_group sys_dmi_attribute_group = {
+       .attrs = sys_dmi_attributes,
+};
+
+static struct attribute_group* sys_dmi_attribute_groups[] = {
+       &sys_dmi_attribute_group,
+       NULL
+};
+
+static int dmi_dev_uevent(struct device *dev, char **envp,
+                           int num_envp, char *buffer, int buffer_size)
+{
+       strcpy(buffer, "MODALIAS=");
+       get_modalias(buffer+9, buffer_size-9);
+       envp[0] = buffer;
+       envp[1] = NULL;
+
+       return 0;
+}
+
+static struct class dmi_class = {
+       .name = "dmi",
+       .dev_release = (void(*)(struct device *)) kfree,
+       .dev_uevent = dmi_dev_uevent,
+};
+
+static struct device *dmi_dev;
+
+/* Initialization */
+
+#define ADD_DMI_ATTR(_name, _field) \
+       if (dmi_get_system_info(_field)) \
+               sys_dmi_attributes[i++] = & sys_dmi_##_name##_attr.attr;
+
+extern int dmi_available;
+
+static int __init dmi_id_init(void)
+{
+       int ret, i;
+
+       if (!dmi_available)
+               return -ENODEV;
+
+       /* Not necessarily all DMI fields are available on all
+        * systems, hence let's built an attribute table of just
+        * what's available */
+       i = 0;
+       ADD_DMI_ATTR(bios_vendor,       DMI_BIOS_VENDOR);
+       ADD_DMI_ATTR(bios_version,      DMI_BIOS_VERSION);
+       ADD_DMI_ATTR(bios_date,         DMI_BIOS_DATE);
+       ADD_DMI_ATTR(sys_vendor,        DMI_SYS_VENDOR);
+       ADD_DMI_ATTR(product_name,      DMI_PRODUCT_NAME);
+       ADD_DMI_ATTR(product_version,   DMI_PRODUCT_VERSION);
+       ADD_DMI_ATTR(product_serial,    DMI_PRODUCT_SERIAL);
+       ADD_DMI_ATTR(product_uuid,      DMI_PRODUCT_UUID);
+       ADD_DMI_ATTR(board_vendor,      DMI_BOARD_VENDOR);
+       ADD_DMI_ATTR(board_name,        DMI_BOARD_NAME);
+       ADD_DMI_ATTR(board_version,     DMI_BOARD_VERSION);
+       ADD_DMI_ATTR(board_serial,      DMI_BOARD_SERIAL);
+       ADD_DMI_ATTR(board_asset_tag,   DMI_BOARD_ASSET_TAG);
+       ADD_DMI_ATTR(chassis_vendor,    DMI_CHASSIS_VENDOR);
+       ADD_DMI_ATTR(chassis_type,      DMI_CHASSIS_TYPE);
+       ADD_DMI_ATTR(chassis_version,   DMI_CHASSIS_VERSION);
+       ADD_DMI_ATTR(chassis_serial,    DMI_CHASSIS_SERIAL);
+       ADD_DMI_ATTR(chassis_asset_tag, DMI_CHASSIS_ASSET_TAG);
+       sys_dmi_attributes[i++] = &sys_dmi_modalias_attr.attr;
+
+       ret = class_register(&dmi_class);
+       if (ret)
+               return ret;
+
+       dmi_dev = kzalloc(sizeof(*dmi_dev), GFP_KERNEL);
+       if (!dmi_dev) {
+               ret = -ENOMEM;
+               goto fail_class_unregister;
+       }
+
+       dmi_dev->class = &dmi_class;
+       strcpy(dmi_dev->bus_id, "id");
+       dmi_dev->groups = sys_dmi_attribute_groups;
+
+       ret = device_register(dmi_dev);
+       if (ret)
+               goto fail_class_unregister;
+
+       return 0;
+
+fail_class_unregister:
+
+       class_unregister(&dmi_class);
+
+       return ret;
+}
+
+arch_initcall(dmi_id_init);
index 37deee6c0c1cc5aa4ca575797dea77d6ad792243..f7318b3b51f2a0860bf2f952896d60f746bd98a8 100644 (file)
@@ -84,6 +84,7 @@ static int __init dmi_checksum(u8 *buf)
 
 static char *dmi_ident[DMI_STRING_MAX];
 static LIST_HEAD(dmi_devices);
+int dmi_available;
 
 /*
  *     Save a DMI string
@@ -102,6 +103,51 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
        dmi_ident[slot] = p;
 }
 
+static void __init dmi_save_uuid(struct dmi_header *dm, int slot, int index)
+{
+       u8 *d = (u8*) dm + index;
+       char *s;
+       int is_ff = 1, is_00 = 1, i;
+
+       if (dmi_ident[slot])
+               return;
+
+       for (i = 0; i < 16 && (is_ff || is_00); i++) {
+               if(d[i] != 0x00) is_ff = 0;
+               if(d[i] != 0xFF) is_00 = 0;
+       }
+
+       if (is_ff || is_00)
+               return;
+
+       s = dmi_alloc(16*2+4+1);
+       if (!s)
+               return;
+
+       sprintf(s,
+               "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+               d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
+               d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
+
+        dmi_ident[slot] = s;
+}
+
+static void __init dmi_save_type(struct dmi_header *dm, int slot, int index)
+{
+       u8 *d = (u8*) dm + index;
+       char *s;
+
+       if (dmi_ident[slot])
+               return;
+
+       s = dmi_alloc(4);
+       if (!s)
+               return;
+
+       sprintf(s, "%u", *d & 0x7F);
+       dmi_ident[slot] = s;
+}
+
 static void __init dmi_save_devices(struct dmi_header *dm)
 {
        int i, count = (dm->length - sizeof(struct dmi_header)) / 2;
@@ -192,11 +238,21 @@ static void __init dmi_decode(struct dmi_header *dm)
                dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
                dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
                dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
+               dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
                break;
        case 2:         /* Base Board Information */
                dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
                dmi_save_ident(dm, DMI_BOARD_NAME, 5);
                dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
+               dmi_save_ident(dm, DMI_BOARD_SERIAL, 7);
+               dmi_save_ident(dm, DMI_BOARD_ASSET_TAG, 8);
+               break;
+       case 3:         /* Chassis Information */
+               dmi_save_ident(dm, DMI_CHASSIS_VENDOR, 4);
+               dmi_save_type(dm, DMI_CHASSIS_TYPE, 5);
+               dmi_save_ident(dm, DMI_CHASSIS_VERSION, 6);
+               dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7);
+               dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8);
                break;
        case 10:        /* Onboard Devices Information */
                dmi_save_devices(dm);
@@ -243,18 +299,20 @@ void __init dmi_scan_machine(void)
                if (efi.smbios == EFI_INVALID_TABLE_ADDR)
                        goto out;
 
-               /* This is called as a core_initcall() because it isn't
-                * needed during early boot.  This also means we can
-                * iounmap the space when we're done with it.
-               */
+               /* This is called as a core_initcall() because it isn't
+                * needed during early boot.  This also means we can
+                * iounmap the space when we're done with it.
+                */
                p = dmi_ioremap(efi.smbios, 32);
                if (p == NULL)
                        goto out;
 
                rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
                dmi_iounmap(p, 32);
-               if (!rc)
+               if (!rc) {
+                       dmi_available = 1;
                        return;
+               }
        }
        else {
                /*
@@ -268,8 +326,10 @@ void __init dmi_scan_machine(void)
 
                for (q = p; q < p + 0x10000; q += 16) {
                        rc = dmi_present(q);
-                       if (!rc)
+                       if (!rc) {
+                               dmi_available = 1;
                                return;
+                       }
                }
        }
  out:  printk(KERN_INFO "DMI not present or invalid.\n");
@@ -404,3 +464,4 @@ int dmi_get_year(int field)
 
        return year;
 }
+
index d8806e4f182984c841603d8d3d365c77d98c6cec..15232271d848c225364df28d17b10dc7d60217be 100644 (file)
@@ -74,7 +74,7 @@ static struct edd_device *edd_devices[EDD_MBR_SIG_MAX];
 
 #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \
 struct edd_attribute edd_attr_##_name = {      \
-       .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
+       .attr = {.name = __stringify(_name), .mode = _mode },   \
        .show   = _show,                                \
        .test   = _test,                                \
 };
index 1324984a4c355e1accf093f05608c0d214579303..bfd2d67df689d8ccb33138c78935b73ae7363d31 100644 (file)
@@ -131,21 +131,21 @@ struct efivar_attribute {
 
 #define EFI_ATTR(_name, _mode, _show, _store) \
 struct subsys_attribute efi_attr_##_name = { \
-       .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+       .attr = {.name = __stringify(_name), .mode = _mode}, \
        .show = _show, \
        .store = _store, \
 };
 
 #define EFIVAR_ATTR(_name, _mode, _show, _store) \
 struct efivar_attribute efivar_attr_##_name = { \
-       .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+       .attr = {.name = __stringify(_name), .mode = _mode}, \
        .show = _show, \
        .store = _store, \
 };
 
 #define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \
 struct subsys_attribute var_subsys_attr_##_name = { \
-       .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+       .attr = {.name = __stringify(_name), .mode = _mode}, \
        .show = _show, \
        .store = _store, \
 };
index 3afa4a5035b7128b6e84fdc835637bdb9c690b74..b2baeaeba9beb2d8a5f598ffec4d24375bab2fb2 100644 (file)
@@ -1009,20 +1009,22 @@ static int hid_resume(struct usb_interface *intf)
 }
 
 /* Treat USB reset pretty much the same as suspend/resume */
-static void hid_pre_reset(struct usb_interface *intf)
+static int hid_pre_reset(struct usb_interface *intf)
 {
        /* FIXME: What if the interface is already suspended? */
        hid_suspend(intf, PMSG_ON);
+       return 0;
 }
 
-static void hid_post_reset(struct usb_interface *intf)
+/* Same routine used for post_reset and reset_resume */
+static int hid_post_reset(struct usb_interface *intf)
 {
        struct usb_device *dev = interface_to_usbdev (intf);
 
        hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
        /* FIXME: Any more reinitialization needed? */
 
-       hid_resume(intf);
+       return hid_resume(intf);
 }
 
 static struct usb_device_id hid_usb_ids [] = {
@@ -1039,6 +1041,7 @@ static struct usb_driver hid_driver = {
        .disconnect =   hid_disconnect,
        .suspend =      hid_suspend,
        .resume =       hid_resume,
+       .reset_resume = hid_post_reset,
        .pre_reset =    hid_pre_reset,
        .post_reset =   hid_post_reset,
        .id_table =     hid_usb_ids,
index 58899078810b787b03dfda4ff894ef43ab2d6709..014dfa575be73e0c156ac77fa08224513cb59d11 100644 (file)
@@ -34,10 +34,6 @@ config I2C_ALGOPCA
          This support is also available as a module.  If so, the module 
          will be called i2c-algo-pca.
 
-config I2C_ALGO8XX
-       tristate "MPC8xx CPM I2C interface"
-       depends on 8xx
-
 config I2C_ALGO_SGI
        tristate "I2C SGI interfaces"
        depends on SGI_IP22 || SGI_IP32 || X86_VISWS
index 838dc1c19d61b4ba0fe7908a9ac851d1c5189a59..fcde9bab5b96e07d510b39221874a015228be34b 100644 (file)
@@ -207,6 +207,7 @@ config I2C_PIIX4
            ATI IXP300
            ATI IXP400
            ATI SB600
+           ATI SB700
            Serverworks OSB4
            Serverworks CSB5
            Serverworks CSB6
@@ -390,11 +391,6 @@ config I2C_PROSAVAGE
          This support is also available as a module.  If so, the module 
          will be called i2c-prosavage.
 
-config I2C_RPXLITE
-       tristate "Embedded Planet RPX Lite/Classic support"
-       depends on RPXLITE || RPXCLASSIC
-       select I2C_ALGO8XX
-
 config I2C_S3C2410
        tristate "S3C2410 I2C Driver"
        depends on ARCH_S3C2410
@@ -512,6 +508,22 @@ config I2C_SIS96X
          This driver can also be built as a module.  If so, the module
          will be called i2c-sis96x.
 
+config I2C_TAOS_EVM
+       tristate "TAOS evaluation module"
+       depends on EXPERIMENTAL
+       select SERIO
+       select SERIO_SERPORT
+       default n
+       help
+         This supports TAOS evaluation modules on serial port. In order to
+         use this driver, you will need the inputattach tool, which is part
+         of the input-utils package.
+
+         If unsure, say N.
+
+         This support is also available as a module.  If so, the module
+         will be called i2c-taos-evm.
+
 config I2C_STUB
        tristate "I2C/SMBus Test Stub"
        depends on EXPERIMENTAL && m
@@ -635,4 +647,13 @@ config I2C_PNX
          This driver can also be built as a module.  If so, the module
          will be called i2c-pnx.
 
+config I2C_PMCMSP
+       tristate "PMC MSP I2C TWI Controller"
+       depends on PMC_MSP
+       help
+         This driver supports the PMC TWI controller on MSP devices.
+
+         This driver can also be built as module. If so, the module
+         will be called i2c-pmcmsp.
+
 endmenu
index 14d1432f698bf9b24ffd6b70917361dd93403238..a6db4e38bda8c237c5db961f88fec40511898dd0 100644 (file)
@@ -32,10 +32,10 @@ obj-$(CONFIG_I2C_PARPORT_LIGHT)     += i2c-parport-light.o
 obj-$(CONFIG_I2C_PASEMI)       += i2c-pasemi.o
 obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
 obj-$(CONFIG_I2C_PIIX4)                += i2c-piix4.o
+obj-$(CONFIG_I2C_PMCMSP)       += i2c-pmcmsp.o
 obj-$(CONFIG_I2C_PNX)          += i2c-pnx.o
 obj-$(CONFIG_I2C_PROSAVAGE)    += i2c-prosavage.o
 obj-$(CONFIG_I2C_PXA)          += i2c-pxa.o
-obj-$(CONFIG_I2C_RPXLITE)      += i2c-rpx.o
 obj-$(CONFIG_I2C_S3C2410)      += i2c-s3c2410.o
 obj-$(CONFIG_I2C_SAVAGE4)      += i2c-savage4.o
 obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
@@ -44,6 +44,7 @@ obj-$(CONFIG_I2C_SIS5595)     += i2c-sis5595.o
 obj-$(CONFIG_I2C_SIS630)       += i2c-sis630.o
 obj-$(CONFIG_I2C_SIS96X)       += i2c-sis96x.o
 obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
+obj-$(CONFIG_I2C_TAOS_EVM)     += i2c-taos-evm.o
 obj-$(CONFIG_I2C_TINY_USB)     += i2c-tiny-usb.o
 obj-$(CONFIG_I2C_VERSATILE)    += i2c-versatile.o
 obj-$(CONFIG_I2C_ACORN)                += i2c-acorn.o
index a7dd54654a9a18d8ecec076668feadc4d3405022..025f19423faffee0df8e88cabf67d630e48cc52f 100644 (file)
@@ -63,14 +63,14 @@ static void i2c_gpio_setscl_val(void *data, int state)
        gpio_set_value(pdata->scl_pin, state);
 }
 
-int i2c_gpio_getsda(void *data)
+static int i2c_gpio_getsda(void *data)
 {
        struct i2c_gpio_platform_data *pdata = data;
 
        return gpio_get_value(pdata->sda_pin);
 }
 
-int i2c_gpio_getscl(void *data)
+static int i2c_gpio_getscl(void *data)
 {
        struct i2c_gpio_platform_data *pdata = data;
 
@@ -142,7 +142,13 @@ static int __init i2c_gpio_probe(struct platform_device *pdev)
        adap->algo_data = bit_data;
        adap->dev.parent = &pdev->dev;
 
-       ret = i2c_bit_add_bus(adap);
+       /*
+        * If "dev->id" is negative we consider it as zero.
+        * The reason to do so is to avoid sysfs names that only make
+        * sense when there are multiple adapters.
+        */
+       adap->nr = pdev->id >= 0 ? pdev->id : 0;
+       ret = i2c_bit_add_numbered_bus(adap);
        if (ret)
                goto err_add_bus;
 
index 611b57192c9618ac6159267b4371f89835efd75c..8f5c686123b8a5da5fae95064cb3bd8355ca5428 100644 (file)
 
 /*
     SUPPORTED DEVICES  PCI ID
-    82801AA            2413           
-    82801AB            2423           
-    82801BA            2443           
-    82801CA/CAM                2483           
-    82801DB            24C3   (HW PEC supported, 32 byte buffer not supported)
-    82801EB            24D3   (HW PEC supported, 32 byte buffer not supported)
+    82801AA            2413
+    82801AB            2423
+    82801BA            2443
+    82801CA/CAM                2483
+    82801DB            24C3   (HW PEC supported)
+    82801EB            24D3   (HW PEC supported)
     6300ESB            25A4
     ICH6               266A
     ICH7               27DA
 #define SMBHSTCFG_SMB_SMI_EN   2
 #define SMBHSTCFG_I2C_EN       4
 
+/* Auxillary control register bits, ICH4+ only */
+#define SMBAUXCTL_CRC          1
+#define SMBAUXCTL_E32B         2
+
+/* kill bit for SMBHSTCNT */
+#define SMBHSTCNT_KILL         2
+
 /* Other settings */
 #define MAX_TIMEOUT            100
 #define ENABLE_INT9            0       /* set to 0x01 to enable - untested */
 #define I801_START             0x40
 #define I801_PEC_EN            0x80    /* ICH4 only */
 
-
-static int i801_transaction(void);
-static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
-                                 int command, int hwpec);
+/* I801 Hosts Status register bits */
+#define SMBHSTSTS_BYTE_DONE    0x80
+#define SMBHSTSTS_INUSE_STS    0x40
+#define SMBHSTSTS_SMBALERT_STS 0x20
+#define SMBHSTSTS_FAILED       0x10
+#define SMBHSTSTS_BUS_ERR      0x08
+#define SMBHSTSTS_DEV_ERR      0x04
+#define SMBHSTSTS_INTR         0x02
+#define SMBHSTSTS_HOST_BUSY    0x01
 
 static unsigned long i801_smba;
 static unsigned char i801_original_hstcfg;
@@ -102,7 +114,7 @@ static struct pci_driver i801_driver;
 static struct pci_dev *I801_dev;
 static int isich4;
 
-static int i801_transaction(void)
+static int i801_transaction(int xact)
 {
        int temp;
        int result = 0;
@@ -127,33 +139,40 @@ static int i801_transaction(void)
                }
        }
 
-       outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
+       /* the current contents of SMBHSTCNT can be overwritten, since PEC,
+        * INTREN, SMBSCMD are passed in xact */
+       outb_p(xact | I801_START, SMBHSTCNT);
 
        /* We will always wait for a fraction of a second! */
        do {
                msleep(1);
                temp = inb_p(SMBHSTSTS);
-       } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
+       } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
 
        /* If the SMBus is still busy, we give up */
        if (timeout >= MAX_TIMEOUT) {
                dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
                result = -1;
+               /* try to stop the current command */
+               dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
+               outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
+               msleep(1);
+               outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
        }
 
-       if (temp & 0x10) {
+       if (temp & SMBHSTSTS_FAILED) {
                result = -1;
                dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
        }
 
-       if (temp & 0x08) {
+       if (temp & SMBHSTSTS_BUS_ERR) {
                result = -1;
                dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
                        "until next hard reset. (sorry!)\n");
                /* Clock stops and slave is stuck in mid-transmission */
        }
 
-       if (temp & 0x04) {
+       if (temp & SMBHSTSTS_DEV_ERR) {
                result = -1;
                dev_dbg(&I801_dev->dev, "Error: no response!\n");
        }
@@ -172,44 +191,70 @@ static int i801_transaction(void)
        return result;
 }
 
-/* All-inclusive block transaction function */
-static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
-                                 int command, int hwpec)
+/* wait for INTR bit as advised by Intel */
+static void i801_wait_hwpec(void)
+{
+       int timeout = 0;
+       int temp;
+
+       do {
+               msleep(1);
+               temp = inb_p(SMBHSTSTS);
+       } while ((!(temp & SMBHSTSTS_INTR))
+                && (timeout++ < MAX_TIMEOUT));
+
+       if (timeout >= MAX_TIMEOUT) {
+               dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
+       }
+       outb_p(temp, SMBHSTSTS);
+}
+
+static int i801_block_transaction_by_block(union i2c_smbus_data *data,
+                                          char read_write, int hwpec)
+{
+       int i, len;
+
+       inb_p(SMBHSTCNT); /* reset the data buffer index */
+
+       /* Use 32-byte buffer to process this transaction */
+       if (read_write == I2C_SMBUS_WRITE) {
+               len = data->block[0];
+               outb_p(len, SMBHSTDAT0);
+               for (i = 0; i < len; i++)
+                       outb_p(data->block[i+1], SMBBLKDAT);
+       }
+
+       if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
+                            I801_PEC_EN * hwpec))
+               return -1;
+
+       if (read_write == I2C_SMBUS_READ) {
+               len = inb_p(SMBHSTDAT0);
+               if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
+                       return -1;
+
+               data->block[0] = len;
+               for (i = 0; i < len; i++)
+                       data->block[i + 1] = inb_p(SMBBLKDAT);
+       }
+       return 0;
+}
+
+static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
+                                              char read_write, int hwpec)
 {
        int i, len;
        int smbcmd;
        int temp;
        int result = 0;
        int timeout;
-       unsigned char hostc, errmask;
+       unsigned char errmask;
 
-       if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
-               if (read_write == I2C_SMBUS_WRITE) {
-                       /* set I2C_EN bit in configuration register */
-                       pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
-                       pci_write_config_byte(I801_dev, SMBHSTCFG,
-                                             hostc | SMBHSTCFG_I2C_EN);
-               } else {
-                       dev_err(&I801_dev->dev,
-                               "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
-                       return -1;
-               }
-       }
+       len = data->block[0];
 
        if (read_write == I2C_SMBUS_WRITE) {
-               len = data->block[0];
-               if (len < 1)
-                       len = 1;
-               if (len > 32)
-                       len = 32;
                outb_p(len, SMBHSTDAT0);
                outb_p(data->block[1], SMBBLKDAT);
-       } else {
-               len = 32;       /* max for reads */
-       }
-
-       if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
-               /* set 32 byte buffer */
        }
 
        for (i = 1; i <= len; i++) {
@@ -227,13 +272,13 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
                /* Make sure the SMBus host is ready to start transmitting */
                temp = inb_p(SMBHSTSTS);
                if (i == 1) {
-                       /* Erronenous conditions before transaction: 
+                       /* Erronenous conditions before transaction:
                         * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
-                       errmask=0x9f; 
+                       errmask = 0x9f;
                } else {
-                       /* Erronenous conditions during transaction: 
+                       /* Erronenous conditions during transaction:
                         * Failed, Bus_Err, Dev_Err, Intr */
-                       errmask=0x1e; 
+                       errmask = 0x1e;
                }
                if (temp & errmask) {
                        dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
@@ -242,14 +287,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
                        if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
                                dev_err(&I801_dev->dev,
                                        "Reset failed! (%02x)\n", temp);
-                               result = -1;
-                                goto END;
+                               return -1;
                        }
-                       if (i != 1) {
+                       if (i != 1)
                                /* if die in middle of block transaction, fail */
-                               result = -1;
-                               goto END;
-                       }
+                               return -1;
                }
 
                if (i == 1)
@@ -261,33 +303,38 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
                        msleep(1);
                        temp = inb_p(SMBHSTSTS);
                }
-                   while ((!(temp & 0x80))
-                          && (timeout++ < MAX_TIMEOUT));
+               while ((!(temp & SMBHSTSTS_BYTE_DONE))
+                      && (timeout++ < MAX_TIMEOUT));
 
                /* If the SMBus is still busy, we give up */
                if (timeout >= MAX_TIMEOUT) {
+                       /* try to stop the current command */
+                       dev_dbg(&I801_dev->dev, "Terminating the current "
+                                               "operation\n");
+                       outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
+                       msleep(1);
+                       outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
+                               SMBHSTCNT);
                        result = -1;
                        dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
                }
 
-               if (temp & 0x10) {
+               if (temp & SMBHSTSTS_FAILED) {
                        result = -1;
                        dev_dbg(&I801_dev->dev,
                                "Error: Failed bus transaction\n");
-               } else if (temp & 0x08) {
+               } else if (temp & SMBHSTSTS_BUS_ERR) {
                        result = -1;
                        dev_err(&I801_dev->dev, "Bus collision!\n");
-               } else if (temp & 0x04) {
+               } else if (temp & SMBHSTSTS_DEV_ERR) {
                        result = -1;
                        dev_dbg(&I801_dev->dev, "Error: no response!\n");
                }
 
                if (i == 1 && read_write == I2C_SMBUS_READ) {
                        len = inb_p(SMBHSTDAT0);
-                       if (len < 1)
-                               len = 1;
-                       if (len > 32)
-                               len = 32;
+                       if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
+                               return -1;
                        data->block[0] = len;
                }
 
@@ -310,25 +357,58 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
                        inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
 
                if (result < 0)
-                       goto END;
+                       return result;
        }
+       return result;
+}
 
-       if (hwpec) {
-               /* wait for INTR bit as advised by Intel */
-               timeout = 0;
-               do {
-                       msleep(1);
-                       temp = inb_p(SMBHSTSTS);
-               } while ((!(temp & 0x02))
-                          && (timeout++ < MAX_TIMEOUT));
+static int i801_set_block_buffer_mode(void)
+{
+       outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
+       if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
+               return -1;
+       return 0;
+}
 
-               if (timeout >= MAX_TIMEOUT) {
-                       dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
+/* Block transaction function */
+static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
+                                 int command, int hwpec)
+{
+       int result = 0;
+       unsigned char hostc;
+
+       if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+               if (read_write == I2C_SMBUS_WRITE) {
+                       /* set I2C_EN bit in configuration register */
+                       pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
+                       pci_write_config_byte(I801_dev, SMBHSTCFG,
+                                             hostc | SMBHSTCFG_I2C_EN);
+               } else {
+                       dev_err(&I801_dev->dev,
+                               "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
+                       return -1;
                }
-               outb_p(temp, SMBHSTSTS); 
        }
-       result = 0;
-END:
+
+       if (read_write == I2C_SMBUS_WRITE) {
+               if (data->block[0] < 1)
+                       data->block[0] = 1;
+               if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
+                       data->block[0] = I2C_SMBUS_BLOCK_MAX;
+       } else {
+               data->block[0] = 32;    /* max for reads */
+       }
+
+       if (isich4 && i801_set_block_buffer_mode() == 0 )
+               result = i801_block_transaction_by_block(data, read_write,
+                                                        hwpec);
+       else
+               result = i801_block_transaction_byte_by_byte(data, read_write,
+                                                            hwpec);
+
+       if (result == 0 && hwpec)
+               i801_wait_hwpec();
+
        if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
                /* restore saved configuration register value */
                pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
@@ -393,19 +473,22 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
                return -1;
        }
 
-       outb_p(hwpec, SMBAUXCTL);       /* enable/disable hardware PEC */
+       if (hwpec)      /* enable/disable hardware PEC */
+               outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
+       else
+               outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
 
        if(block)
                ret = i801_block_transaction(data, read_write, size, hwpec);
-       else {
-               outb_p(xact | ENABLE_INT9, SMBHSTCNT);
-               ret = i801_transaction();
-       }
+       else
+               ret = i801_transaction(xact | ENABLE_INT9);
 
        /* Some BIOSes don't like it when PEC is enabled at reboot or resume
-          time, so we forcibly disable it after every transaction. */
+          time, so we forcibly disable it after every transaction. Turn off
+          E32B for the same reason. */
        if (hwpec)
-               outb_p(0, SMBAUXCTL);
+               outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
+                      SMBAUXCTL);
 
        if(block)
                return ret;
index 90e2d9350c1bd12d390a2495872c837cc5959a5f..440342bc62e183d0d20b8acced8ea0a9a5cd5b86 100644 (file)
@@ -491,6 +491,7 @@ iop3xx_i2c_probe(struct platform_device *pdev)
        new_adapter->id = I2C_HW_IOP3XX;
        new_adapter->owner = THIS_MODULE;
        new_adapter->dev.parent = &pdev->dev;
+       new_adapter->nr = pdev->id;
 
        /*
         * Default values...should these come in from board code?
@@ -508,7 +509,7 @@ iop3xx_i2c_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, new_adapter);
        new_adapter->algo_data = adapter_data;
 
-       i2c_add_adapter(new_adapter);
+       i2c_add_numbered_adapter(new_adapter);
 
        return 0;
 
index c6b6898592b19af7573dbe0d5b19322775959a07..851c3ed513d015e50b5c75c362a014dfa09c1c1d 100644 (file)
@@ -74,6 +74,25 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+/* Sometimes 9th clock pulse isn't generated, and slave doesn't release
+ * the bus, because it wants to send ACK.
+ * Following sequence of enabling/disabling and sending start/stop generates
+ * the pulse, so it's all OK.
+ */
+static void mpc_i2c_fixup(struct mpc_i2c *i2c)
+{
+       writeccr(i2c, 0);
+       udelay(30);
+       writeccr(i2c, CCR_MEN);
+       udelay(30);
+       writeccr(i2c, CCR_MSTA | CCR_MTX);
+       udelay(30);
+       writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+       udelay(30);
+       writeccr(i2c, CCR_MEN);
+       udelay(30);
+}
+
 static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
 {
        unsigned long orig_jiffies = jiffies;
@@ -153,6 +172,7 @@ static void mpc_i2c_start(struct mpc_i2c *i2c)
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
        writeccr(i2c, CCR_MEN);
+       writeccr(i2c, 0);
 }
 
 static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -245,6 +265,9 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
                }
                if (time_after(jiffies, orig_jiffies + HZ)) {
                        pr_debug("I2C: timeout\n");
+                       if (readb(i2c->base + MPC_I2C_SR) ==
+                           (CSR_MCF | CSR_MBB | CSR_RXAK))
+                               mpc_i2c_fixup(i2c);
                        return -EIO;
                }
                schedule();
@@ -327,9 +350,10 @@ static int fsl_i2c_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, i2c);
 
        i2c->adap = mpc_ops;
+       i2c->adap.nr = pdev->id;
        i2c_set_adapdata(&i2c->adap, i2c);
        i2c->adap.dev.parent = &pdev->dev;
-       if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
+       if ((result = i2c_add_numbered_adapter(&i2c->adap)) < 0) {
                printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
                goto fail_add;
        }
index a55b3335d1becd05d5ebbcafb8d4477b50f9d099..251154ae5d97ad3eb0bddff1067c3a655075ba5f 100644 (file)
@@ -527,6 +527,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
        drv_data->adapter.class = I2C_CLASS_HWMON;
        drv_data->adapter.timeout = pdata->timeout;
        drv_data->adapter.retries = pdata->retries;
+       drv_data->adapter.nr = pd->id;
        platform_set_drvdata(pd, drv_data);
        i2c_set_adapdata(&drv_data->adapter, drv_data);
 
@@ -539,7 +540,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
                        drv_data->irq);
                rc = -EINVAL;
                goto exit_unmap_regs;
-       } else if ((rc = i2c_add_adapter(&drv_data->adapter)) != 0) {
+       } else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) {
                dev_err(&drv_data->adapter.dev,
                        "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc);
                goto exit_free_irq;
index 3cd0d63e7b501c047e04e52945211e988409b0a1..c48140f782d09c276dcb4c6b31d5201dd213b6dd 100644 (file)
@@ -61,6 +61,7 @@ struct nforce2_smbus {
        struct i2c_adapter adapter;
        int base;
        int size;
+       int blockops;
 };
 
 
@@ -80,6 +81,8 @@ struct nforce2_smbus {
 #define NVIDIA_SMB_ADDR                (smbus->base + 0x02)    /* address */
 #define NVIDIA_SMB_CMD         (smbus->base + 0x03)    /* command */
 #define NVIDIA_SMB_DATA                (smbus->base + 0x04)    /* 32 data registers */
+#define NVIDIA_SMB_BCNT                (smbus->base + 0x24)    /* number of data
+                                                          bytes */
 
 #define NVIDIA_SMB_STS_DONE    0x80
 #define NVIDIA_SMB_STS_ALRM    0x40
@@ -92,6 +95,7 @@ struct nforce2_smbus {
 #define NVIDIA_SMB_PRTCL_BYTE                  0x04
 #define NVIDIA_SMB_PRTCL_BYTE_DATA             0x06
 #define NVIDIA_SMB_PRTCL_WORD_DATA             0x08
+#define NVIDIA_SMB_PRTCL_BLOCK_DATA            0x0a
 #define NVIDIA_SMB_PRTCL_PEC                   0x80
 
 static struct pci_driver nforce2_driver;
@@ -103,6 +107,8 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
 {
        struct nforce2_smbus *smbus = adap->algo_data;
        unsigned char protocol, pec, temp;
+       u8 len;
+       int i;
 
        protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
                NVIDIA_SMB_PRTCL_WRITE;
@@ -137,6 +143,25 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
                        protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;
                        break;
 
+               case I2C_SMBUS_BLOCK_DATA:
+                       outb_p(command, NVIDIA_SMB_CMD);
+                       if (read_write == I2C_SMBUS_WRITE) {
+                               len = data->block[0];
+                               if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) {
+                                       dev_err(&adap->dev,
+                                               "Transaction failed "
+                                               "(requested block size: %d)\n",
+                                               len);
+                                       return -1;
+                               }
+                               outb_p(len, NVIDIA_SMB_BCNT);
+                               for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
+                                       outb_p(data->block[i + 1],
+                                              NVIDIA_SMB_DATA+i);
+                       }
+                       protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec;
+                       break;
+
                default:
                        dev_err(&adap->dev, "Unsupported transaction %d\n", size);
                        return -1;
@@ -174,6 +199,14 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
                case I2C_SMBUS_WORD_DATA:
                        data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8);
                        break;
+
+               case I2C_SMBUS_BLOCK_DATA:
+                       len = inb_p(NVIDIA_SMB_BCNT);
+                       len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
+                       for (i = 0; i < len; i++)
+                               data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i);
+                       data->block[0] = len;
+                       break;
        }
 
        return 0;
@@ -184,7 +217,9 @@ static u32 nforce2_func(struct i2c_adapter *adapter)
 {
        /* other functionality might be possible, but is not tested */
        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
-           I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
+              I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+              (((struct nforce2_smbus*)adapter->algo_data)->blockops ?
+               I2C_FUNC_SMBUS_BLOCK_DATA : 0);
 }
 
 static struct i2c_algorithm smbus_algorithm = {
@@ -268,6 +303,13 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
                return -ENOMEM;
        pci_set_drvdata(dev, smbuses);
 
+       switch(dev->device) {
+       case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS:
+       case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS:
+               smbuses[0].blockops = 1;
+               smbuses[1].blockops = 1;
+       }
+
        /* SMBus adapter 1 */
        res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1");
        if (res1 < 0) {
index 5a52bf5e3fb0a8c2f93263fa4e95e85e1b50763f..debc76cd2161c64b1c675d196ec8d40e3b9c8e50 100644 (file)
@@ -23,7 +23,7 @@
    Supports:
        Intel PIIX4, 440MX
        Serverworks OSB4, CSB5, CSB6, HT-1000
-       ATI IXP200, IXP300, IXP400, SB600
+       ATI IXP200, IXP300, IXP400, SB600, SB700
        SMSC Victory66
 
    Note: we assume there can only be one device, with one SMBus interface.
@@ -399,6 +399,8 @@ static struct pci_device_id piix4_ids[] = {
          .driver_data = 0 },
        { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SMBUS),
          .driver_data = 0 },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SMBUS),
+         .driver_data = 0 },
        { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
          .driver_data = 0 },
        { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
new file mode 100644 (file)
index 0000000..03188d2
--- /dev/null
@@ -0,0 +1,653 @@
+/*
+ * Specific bus support for PMC-TWI compliant implementation on MSP71xx.
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#define DRV_NAME       "pmcmsptwi"
+
+#define MSP_TWI_SF_CLK_REG_OFFSET      0x00
+#define MSP_TWI_HS_CLK_REG_OFFSET      0x04
+#define MSP_TWI_CFG_REG_OFFSET         0x08
+#define MSP_TWI_CMD_REG_OFFSET         0x0c
+#define MSP_TWI_ADD_REG_OFFSET         0x10
+#define MSP_TWI_DAT_0_REG_OFFSET       0x14
+#define MSP_TWI_DAT_1_REG_OFFSET       0x18
+#define MSP_TWI_INT_STS_REG_OFFSET     0x1c
+#define MSP_TWI_INT_MSK_REG_OFFSET     0x20
+#define MSP_TWI_BUSY_REG_OFFSET                0x24
+
+#define MSP_TWI_INT_STS_DONE                   (1 << 0)
+#define MSP_TWI_INT_STS_LOST_ARBITRATION       (1 << 1)
+#define MSP_TWI_INT_STS_NO_RESPONSE            (1 << 2)
+#define MSP_TWI_INT_STS_DATA_COLLISION         (1 << 3)
+#define MSP_TWI_INT_STS_BUSY                   (1 << 4)
+#define MSP_TWI_INT_STS_ALL                    0x1f
+
+#define MSP_MAX_BYTES_PER_RW           8
+#define MSP_MAX_POLL                   5
+#define MSP_POLL_DELAY                 10
+#define MSP_IRQ_TIMEOUT                        (MSP_MAX_POLL * MSP_POLL_DELAY)
+
+/* IO Operation macros */
+#define pmcmsptwi_readl                __raw_readl
+#define pmcmsptwi_writel       __raw_writel
+
+/* TWI command type */
+enum pmcmsptwi_cmd_type {
+       MSP_TWI_CMD_WRITE       = 0,    /* Write only */
+       MSP_TWI_CMD_READ        = 1,    /* Read only */
+       MSP_TWI_CMD_WRITE_READ  = 2,    /* Write then Read */
+};
+
+/* The possible results of the xferCmd */
+enum pmcmsptwi_xfer_result {
+       MSP_TWI_XFER_OK = 0,
+       MSP_TWI_XFER_TIMEOUT,
+       MSP_TWI_XFER_BUSY,
+       MSP_TWI_XFER_DATA_COLLISION,
+       MSP_TWI_XFER_NO_RESPONSE,
+       MSP_TWI_XFER_LOST_ARBITRATION,
+};
+
+/* Corresponds to a PMCTWI clock configuration register */
+struct pmcmsptwi_clock {
+       u8 filter;      /* Bits 15:12,  default = 0x03 */
+       u16 clock;      /* Bits 9:0,    default = 0x001f */
+};
+
+struct pmcmsptwi_clockcfg {
+       struct pmcmsptwi_clock standard;  /* The standard/fast clock config */
+       struct pmcmsptwi_clock highspeed; /* The highspeed clock config */
+};
+
+/* Corresponds to the main TWI configuration register */
+struct pmcmsptwi_cfg {
+       u8 arbf;        /* Bits 15:12,  default=0x03 */
+       u8 nak;         /* Bits 11:8,   default=0x03 */
+       u8 add10;       /* Bit 7,       default=0x00 */
+       u8 mst_code;    /* Bits 6:4,    default=0x00 */
+       u8 arb;         /* Bit 1,       default=0x01 */
+       u8 highspeed;   /* Bit 0,       default=0x00 */
+};
+
+/* A single pmctwi command to issue */
+struct pmcmsptwi_cmd {
+       u16 addr;       /* The slave address (7 or 10 bits) */
+       enum pmcmsptwi_cmd_type type;   /* The command type */
+       u8 write_len;   /* Number of bytes in the write buffer */
+       u8 read_len;    /* Number of bytes in the read buffer */
+       u8 *write_data; /* Buffer of characters to send */
+       u8 *read_data;  /* Buffer to fill with incoming data */
+};
+
+/* The private data */
+struct pmcmsptwi_data {
+       void __iomem *iobase;                   /* iomapped base for IO */
+       int irq;                                /* IRQ to use (0 disables) */
+       struct completion wait;                 /* Completion for xfer */
+       struct mutex lock;                      /* Used for threadsafeness */
+       enum pmcmsptwi_xfer_result last_result; /* result of last xfer */
+};
+
+/* The default settings */
+const static struct pmcmsptwi_clockcfg pmcmsptwi_defclockcfg = {
+       .standard = {
+               .filter = 0x3,
+               .clock  = 0x1f,
+       },
+       .highspeed = {
+               .filter = 0x3,
+               .clock  = 0x1f,
+       },
+};
+
+const static struct pmcmsptwi_cfg pmcmsptwi_defcfg = {
+       .arbf           = 0x03,
+       .nak            = 0x03,
+       .add10          = 0x00,
+       .mst_code       = 0x00,
+       .arb            = 0x01,
+       .highspeed      = 0x00,
+};
+
+static struct pmcmsptwi_data pmcmsptwi_data;
+
+static struct i2c_adapter pmcmsptwi_adapter;
+
+/* inline helper functions */
+static inline u32 pmcmsptwi_clock_to_reg(
+                       const struct pmcmsptwi_clock *clock)
+{
+       return ((clock->filter & 0xf) << 12) | (clock->clock & 0x03ff);
+}
+
+static inline void pmcmsptwi_reg_to_clock(
+                       u32 reg, struct pmcmsptwi_clock *clock)
+{
+       clock->filter = (reg >> 12) & 0xf;
+       clock->clock = reg & 0x03ff;
+}
+
+static inline u32 pmcmsptwi_cfg_to_reg(const struct pmcmsptwi_cfg *cfg)
+{
+       return ((cfg->arbf & 0xf) << 12) |
+               ((cfg->nak & 0xf) << 8) |
+               ((cfg->add10 & 0x1) << 7) |
+               ((cfg->mst_code & 0x7) << 4) |
+               ((cfg->arb & 0x1) << 1) |
+               (cfg->highspeed & 0x1);
+}
+
+static inline void pmcmsptwi_reg_to_cfg(u32 reg, struct pmcmsptwi_cfg *cfg)
+{
+       cfg->arbf = (reg >> 12) & 0xf;
+       cfg->nak = (reg >> 8) & 0xf;
+       cfg->add10 = (reg >> 7) & 0x1;
+       cfg->mst_code = (reg >> 4) & 0x7;
+       cfg->arb = (reg >> 1) & 0x1;
+       cfg->highspeed = reg & 0x1;
+}
+
+/*
+ * Sets the current clock configuration
+ */
+static void pmcmsptwi_set_clock_config(const struct pmcmsptwi_clockcfg *cfg,
+                                       struct pmcmsptwi_data *data)
+{
+       mutex_lock(&data->lock);
+       pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->standard),
+                               data->iobase + MSP_TWI_SF_CLK_REG_OFFSET);
+       pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->highspeed),
+                               data->iobase + MSP_TWI_HS_CLK_REG_OFFSET);
+       mutex_unlock(&data->lock);
+}
+
+/*
+ * Gets the current TWI bus configuration
+ */
+static void pmcmsptwi_get_twi_config(struct pmcmsptwi_cfg *cfg,
+                                       struct pmcmsptwi_data *data)
+{
+       mutex_lock(&data->lock);
+       pmcmsptwi_reg_to_cfg(pmcmsptwi_readl(
+                               data->iobase + MSP_TWI_CFG_REG_OFFSET), cfg);
+       mutex_unlock(&data->lock);
+}
+
+/*
+ * Sets the current TWI bus configuration
+ */
+static void pmcmsptwi_set_twi_config(const struct pmcmsptwi_cfg *cfg,
+                                       struct pmcmsptwi_data *data)
+{
+       mutex_lock(&data->lock);
+       pmcmsptwi_writel(pmcmsptwi_cfg_to_reg(cfg),
+                               data->iobase + MSP_TWI_CFG_REG_OFFSET);
+       mutex_unlock(&data->lock);
+}
+
+/*
+ * Parses the 'int_sts' register and returns a well-defined error code
+ */
+static enum pmcmsptwi_xfer_result pmcmsptwi_get_result(u32 reg)
+{
+       if (reg & MSP_TWI_INT_STS_LOST_ARBITRATION) {
+               dev_dbg(&pmcmsptwi_adapter.dev,
+                       "Result: Lost arbitration\n");
+               return MSP_TWI_XFER_LOST_ARBITRATION;
+       } else if (reg & MSP_TWI_INT_STS_NO_RESPONSE) {
+               dev_dbg(&pmcmsptwi_adapter.dev,
+                       "Result: No response\n");
+               return MSP_TWI_XFER_NO_RESPONSE;
+       } else if (reg & MSP_TWI_INT_STS_DATA_COLLISION) {
+               dev_dbg(&pmcmsptwi_adapter.dev,
+                       "Result: Data collision\n");
+               return MSP_TWI_XFER_DATA_COLLISION;
+       } else if (reg & MSP_TWI_INT_STS_BUSY) {
+               dev_dbg(&pmcmsptwi_adapter.dev,
+                       "Result: Bus busy\n");
+               return MSP_TWI_XFER_BUSY;
+       }
+
+       dev_dbg(&pmcmsptwi_adapter.dev, "Result: Operation succeeded\n");
+       return MSP_TWI_XFER_OK;
+}
+
+/*
+ * In interrupt mode, handle the interrupt.
+ * NOTE: Assumes data->lock is held.
+ */
+static irqreturn_t pmcmsptwi_interrupt(int irq, void *ptr)
+{
+       struct pmcmsptwi_data *data = ptr;
+
+       u32 reason = pmcmsptwi_readl(data->iobase +
+                                       MSP_TWI_INT_STS_REG_OFFSET);
+       pmcmsptwi_writel(reason, data->iobase + MSP_TWI_INT_STS_REG_OFFSET);
+
+       dev_dbg(&pmcmsptwi_adapter.dev, "Got interrupt 0x%08x\n", reason);
+       if (!(reason & MSP_TWI_INT_STS_DONE))
+               return IRQ_NONE;
+
+       data->last_result = pmcmsptwi_get_result(reason);
+       complete(&data->wait);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * Probe for and register the device and return 0 if there is one.
+ */
+static int __devinit pmcmsptwi_probe(struct platform_device *pldev)
+{
+       struct resource *res;
+       int rc = -ENODEV;
+
+       /* get the static platform resources */
+       res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pldev->dev, "IOMEM resource not found\n");
+               goto ret_err;
+       }
+
+       /* reserve the memory region */
+       if (!request_mem_region(res->start, res->end - res->start + 1,
+                               pldev->name)) {
+               dev_err(&pldev->dev,
+                       "Unable to get memory/io address region 0x%08x\n",
+                       res->start);
+               rc = -EBUSY;
+               goto ret_err;
+       }
+
+       /* remap the memory */
+       pmcmsptwi_data.iobase = ioremap_nocache(res->start,
+                                               res->end - res->start + 1);
+       if (!pmcmsptwi_data.iobase) {
+               dev_err(&pldev->dev,
+                       "Unable to ioremap address 0x%08x\n", res->start);
+               rc = -EIO;
+               goto ret_unreserve;
+       }
+
+       /* request the irq */
+       pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
+       if (pmcmsptwi_data.irq) {
+               rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
+                       IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+                       pldev->name, &pmcmsptwi_data);
+               if (rc == 0) {
+                       /*
+                        * Enable 'DONE' interrupt only.
+                        *
+                        * If you enable all interrupts, you will get one on
+                        * error and another when the operation completes.
+                        * This way you only have to handle one interrupt,
+                        * but you can still check all result flags.
+                        */
+                       pmcmsptwi_writel(MSP_TWI_INT_STS_DONE,
+                                       pmcmsptwi_data.iobase +
+                                       MSP_TWI_INT_MSK_REG_OFFSET);
+               } else {
+                       dev_warn(&pldev->dev,
+                               "Could not assign TWI IRQ handler "
+                               "to irq %d (continuing with poll)\n",
+                               pmcmsptwi_data.irq);
+                       pmcmsptwi_data.irq = 0;
+               }
+       }
+
+       init_completion(&pmcmsptwi_data.wait);
+       mutex_init(&pmcmsptwi_data.lock);
+
+       pmcmsptwi_set_clock_config(&pmcmsptwi_defclockcfg, &pmcmsptwi_data);
+       pmcmsptwi_set_twi_config(&pmcmsptwi_defcfg, &pmcmsptwi_data);
+
+       printk(KERN_INFO DRV_NAME ": Registering MSP71xx I2C adapter\n");
+
+       pmcmsptwi_adapter.dev.parent = &pldev->dev;
+       platform_set_drvdata(pldev, &pmcmsptwi_adapter);
+       i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data);
+
+       rc = i2c_add_adapter(&pmcmsptwi_adapter);
+       if (rc) {
+               dev_err(&pldev->dev, "Unable to register I2C adapter\n");
+               goto ret_unmap;
+       }
+
+       return 0;
+
+ret_unmap:
+       platform_set_drvdata(pldev, NULL);
+       if (pmcmsptwi_data.irq) {
+               pmcmsptwi_writel(0,
+                       pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET);
+               free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data);
+       }
+
+       iounmap(pmcmsptwi_data.iobase);
+
+ret_unreserve:
+       release_mem_region(res->start, res->end - res->start + 1);
+
+ret_err:
+       return rc;
+}
+
+/*
+ * Release the device and return 0 if there is one.
+ */
+static int __devexit pmcmsptwi_remove(struct platform_device *pldev)
+{
+       struct resource *res;
+
+       i2c_del_adapter(&pmcmsptwi_adapter);
+
+       platform_set_drvdata(pldev, NULL);
+       if (pmcmsptwi_data.irq) {
+               pmcmsptwi_writel(0,
+                       pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET);
+               free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data);
+       }
+
+       iounmap(pmcmsptwi_data.iobase);
+
+       res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, res->end - res->start + 1);
+
+       return 0;
+}
+
+/*
+ * Polls the 'busy' register until the command is complete.
+ * NOTE: Assumes data->lock is held.
+ */
+static void pmcmsptwi_poll_complete(struct pmcmsptwi_data *data)
+{
+       int i;
+
+       for (i = 0; i < MSP_MAX_POLL; i++) {
+               u32 val = pmcmsptwi_readl(data->iobase +
+                                               MSP_TWI_BUSY_REG_OFFSET);
+               if (val == 0) {
+                       u32 reason = pmcmsptwi_readl(data->iobase +
+                                               MSP_TWI_INT_STS_REG_OFFSET);
+                       pmcmsptwi_writel(reason, data->iobase +
+                                               MSP_TWI_INT_STS_REG_OFFSET);
+                       data->last_result = pmcmsptwi_get_result(reason);
+                       return;
+               }
+               udelay(MSP_POLL_DELAY);
+       }
+
+       dev_dbg(&pmcmsptwi_adapter.dev, "Result: Poll timeout\n");
+       data->last_result = MSP_TWI_XFER_TIMEOUT;
+}
+
+/*
+ * Do the transfer (low level):
+ *   May use interrupt-driven or polling, depending on if an IRQ is
+ *   presently registered.
+ * NOTE: Assumes data->lock is held.
+ */
+static enum pmcmsptwi_xfer_result pmcmsptwi_do_xfer(
+                       u32 reg, struct pmcmsptwi_data *data)
+{
+       dev_dbg(&pmcmsptwi_adapter.dev, "Writing cmd reg 0x%08x\n", reg);
+       pmcmsptwi_writel(reg, data->iobase + MSP_TWI_CMD_REG_OFFSET);
+       if (data->irq) {
+               unsigned long timeleft = wait_for_completion_timeout(
+                                               &data->wait, MSP_IRQ_TIMEOUT);
+               if (timeleft == 0) {
+                       dev_dbg(&pmcmsptwi_adapter.dev,
+                               "Result: IRQ timeout\n");
+                       complete(&data->wait);
+                       data->last_result = MSP_TWI_XFER_TIMEOUT;
+               }
+       } else
+               pmcmsptwi_poll_complete(data);
+
+       return data->last_result;
+}
+
+/*
+ * Helper routine, converts 'pmctwi_cmd' struct to register format
+ */
+static inline u32 pmcmsptwi_cmd_to_reg(const struct pmcmsptwi_cmd *cmd)
+{
+       return ((cmd->type & 0x3) << 8) |
+               (((cmd->write_len - 1) & 0x7) << 4) |
+               ((cmd->read_len - 1) & 0x7);
+}
+
+/*
+ * Do the transfer (high level)
+ */
+static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
+                       struct pmcmsptwi_cmd *cmd,
+                       struct pmcmsptwi_data *data)
+{
+       enum pmcmsptwi_xfer_result retval;
+
+       if ((cmd->type == MSP_TWI_CMD_WRITE && cmd->write_len == 0) ||
+           (cmd->type == MSP_TWI_CMD_READ && cmd->read_len == 0) ||
+           (cmd->type == MSP_TWI_CMD_WRITE_READ &&
+           (cmd->read_len == 0 || cmd->write_len == 0))) {
+               dev_err(&pmcmsptwi_adapter.dev,
+                       "%s: Cannot transfer less than 1 byte\n",
+                       __FUNCTION__);
+               return -EINVAL;
+       }
+
+       if (cmd->read_len > MSP_MAX_BYTES_PER_RW ||
+           cmd->write_len > MSP_MAX_BYTES_PER_RW) {
+               dev_err(&pmcmsptwi_adapter.dev,
+                       "%s: Cannot transfer more than %d bytes\n",
+                       __FUNCTION__, MSP_MAX_BYTES_PER_RW);
+               return -EINVAL;
+       }
+
+       mutex_lock(&data->lock);
+       dev_dbg(&pmcmsptwi_adapter.dev,
+               "Setting address to 0x%04x\n", cmd->addr);
+       pmcmsptwi_writel(cmd->addr, data->iobase + MSP_TWI_ADD_REG_OFFSET);
+
+       if (cmd->type == MSP_TWI_CMD_WRITE ||
+           cmd->type == MSP_TWI_CMD_WRITE_READ) {
+               __be64 tmp = cpu_to_be64p((u64 *)cmd->write_data);
+               tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8;
+               dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp);
+               pmcmsptwi_writel(tmp & 0x00000000ffffffffLL,
+                               data->iobase + MSP_TWI_DAT_0_REG_OFFSET);
+               if (cmd->write_len > 4)
+                       pmcmsptwi_writel(tmp >> 32,
+                               data->iobase + MSP_TWI_DAT_1_REG_OFFSET);
+       }
+
+       retval = pmcmsptwi_do_xfer(pmcmsptwi_cmd_to_reg(cmd), data);
+       if (retval != MSP_TWI_XFER_OK)
+               goto xfer_err;
+
+       if (cmd->type == MSP_TWI_CMD_READ ||
+           cmd->type == MSP_TWI_CMD_WRITE_READ) {
+               int i;
+               u64 rmsk = ~(0xffffffffffffffffLL << (cmd->read_len * 8));
+               u64 tmp = (u64)pmcmsptwi_readl(data->iobase +
+                                       MSP_TWI_DAT_0_REG_OFFSET);
+               if (cmd->read_len > 4)
+                       tmp |= (u64)pmcmsptwi_readl(data->iobase +
+                                       MSP_TWI_DAT_1_REG_OFFSET) << 32;
+               tmp &= rmsk;
+               dev_dbg(&pmcmsptwi_adapter.dev, "Read 0x%016llx\n", tmp);
+
+               for (i = 0; i < cmd->read_len; i++)
+                       cmd->read_data[i] = tmp >> i;
+       }
+
+xfer_err:
+       mutex_unlock(&data->lock);
+
+       return retval;
+}
+
+/* -- Algorithm functions -- */
+
+/*
+ * Sends an i2c command out on the adapter
+ */
+static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
+                               struct i2c_msg *msg, int num)
+{
+       struct pmcmsptwi_data *data = i2c_get_adapdata(adap);
+       struct pmcmsptwi_cmd cmd;
+       struct pmcmsptwi_cfg oldcfg, newcfg;
+       int ret;
+
+       if (num > 2) {
+               dev_dbg(&adap->dev, "%d messages unsupported\n", num);
+               return -EINVAL;
+       } else if (num == 2) {
+               /* Check for a dual write-then-read command */
+               struct i2c_msg *nextmsg = msg + 1;
+               if (!(msg->flags & I2C_M_RD) &&
+                   (nextmsg->flags & I2C_M_RD) &&
+                   msg->addr == nextmsg->addr) {
+                       cmd.type = MSP_TWI_CMD_WRITE_READ;
+                       cmd.write_len = msg->len;
+                       cmd.write_data = msg->buf;
+                       cmd.read_len = nextmsg->len;
+                       cmd.read_data = nextmsg->buf;
+               } else {
+                       dev_dbg(&adap->dev,
+                               "Non write-read dual messages unsupported\n");
+                       return -EINVAL;
+               }
+       } else if (msg->flags & I2C_M_RD) {
+               cmd.type = MSP_TWI_CMD_READ;
+               cmd.read_len = msg->len;
+               cmd.read_data = msg->buf;
+               cmd.write_len = 0;
+               cmd.write_data = NULL;
+       } else {
+               cmd.type = MSP_TWI_CMD_WRITE;
+               cmd.read_len = 0;
+               cmd.read_data = NULL;
+               cmd.write_len = msg->len;
+               cmd.write_data = msg->buf;
+       }
+
+       if (msg->len == 0) {
+               dev_err(&adap->dev, "Zero-byte messages unsupported\n");
+               return -EINVAL;
+       }
+
+       cmd.addr = msg->addr;
+
+       if (msg->flags & I2C_M_TEN) {
+               pmcmsptwi_get_twi_config(&newcfg, data);
+               memcpy(&oldcfg, &newcfg, sizeof(oldcfg));
+
+               /* Set the special 10-bit address flag */
+               newcfg.add10 = 1;
+
+               pmcmsptwi_set_twi_config(&newcfg, data);
+       }
+
+       /* Execute the command */
+       ret = pmcmsptwi_xfer_cmd(&cmd, data);
+
+       if (msg->flags & I2C_M_TEN)
+               pmcmsptwi_set_twi_config(&oldcfg, data);
+
+       dev_dbg(&adap->dev, "I2C %s of %d bytes ",
+               (msg->flags & I2C_M_RD) ? "read" : "write", msg->len);
+       if (ret != MSP_TWI_XFER_OK) {
+               /*
+                * TODO: We could potentially loop and retry in the case
+                * of MSP_TWI_XFER_TIMEOUT.
+                */
+               dev_dbg(&adap->dev, "failed\n");
+               return -1;
+       }
+
+       dev_dbg(&adap->dev, "succeeded\n");
+       return 0;
+}
+
+static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR |
+               I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
+               I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL;
+}
+
+/* -- Initialization -- */
+
+static struct i2c_algorithm pmcmsptwi_algo = {
+       .master_xfer    = pmcmsptwi_master_xfer,
+       .functionality  = pmcmsptwi_i2c_func,
+};
+
+static struct i2c_adapter pmcmsptwi_adapter = {
+       .owner          = THIS_MODULE,
+       .class          = I2C_CLASS_HWMON,
+       .algo           = &pmcmsptwi_algo,
+       .name           = DRV_NAME,
+};
+
+static struct platform_driver pmcmsptwi_driver = {
+       .probe  = pmcmsptwi_probe,
+       .remove = __devexit_p(pmcmsptwi_remove),
+       .driver {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init pmcmsptwi_init(void)
+{
+       return platform_driver_register(&pmcmsptwi_driver);
+}
+
+static void __exit pmcmsptwi_exit(void)
+{
+       platform_driver_unregister(&pmcmsptwi_driver);
+}
+
+MODULE_DESCRIPTION("PMC MSP TWI/SMBus/I2C driver");
+MODULE_LICENSE("GPL");
+
+module_init(pmcmsptwi_init);
+module_exit(pmcmsptwi_exit);
index 1425d2245c827f8f9a103a3f74dfb3a7cfb70df3..0ab4f2627c26c58c3eb53fb593da0fffe7f03bff 100644 (file)
@@ -121,8 +121,7 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter*     adap,
                if (rc)
                        goto bail;
                rc = pmac_i2c_xfer(bus, addrdir, 1, command,
-                                  read ? data->block : &data->block[1],
-                                  data->block[0]);
+                                  &data->block[1], data->block[0]);
                break;
 
         default:
index 28e7b91a4553ff3d33f5e830fb881a0e7c8f6886..9d6b790d43210fa3e21ff7b3b3c9fc6b6011c941 100644 (file)
@@ -921,7 +921,14 @@ static int i2c_pxa_probe(struct platform_device *dev)
                i2c->adap.class = plat->class;
        }
 
-       ret = i2c_add_adapter(&i2c->adap);
+       /*
+        * If "dev->id" is negative we consider it as zero.
+        * The reason to do so is to avoid sysfs names that only make
+        * sense when there are multiple adapters.
+        */
+       i2c->adap.nr = dev->id >= 0 ? dev->id : 0;
+
+       ret = i2c_add_numbered_adapter(&i2c->adap);
        if (ret < 0) {
                printk(KERN_INFO "I2C: Failed to add bus\n");
                goto eadapt;
diff --git a/drivers/i2c/busses/i2c-rpx.c b/drivers/i2c/busses/i2c-rpx.c
deleted file mode 100644 (file)
index 8764df0..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Embedded Planet RPX Lite MPC8xx CPM I2C interface.
- * Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
- *
- * moved into proper i2c interface;
- * Brad Parker (brad@heeltoe.com)
- *
- * RPX lite specific parts of the i2c interface
- * Update:  There actually isn't anything RPXLite-specific about this module.
- * This should work for most any 8xx board.  The console messages have been 
- * changed to eliminate RPXLite references.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/stddef.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-8xx.h>
-#include <asm/mpc8xx.h>
-#include <asm/commproc.h>
-
-
-static void
-rpx_iic_init(struct i2c_algo_8xx_data *data)
-{
-       volatile cpm8xx_t *cp;
-       volatile immap_t *immap;
-
-       cp = cpmp;      /* Get pointer to Communication Processor */
-       immap = (immap_t *)IMAP_ADDR;   /* and to internal registers */
-
-       data->iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
-
-       /* Check for and use a microcode relocation patch.
-       */
-       if ((data->reloc = data->iip->iic_rpbase))
-               data->iip = (iic_t *)&cp->cp_dpmem[data->iip->iic_rpbase];
-               
-       data->i2c = (i2c8xx_t *)&(immap->im_i2c);
-       data->cp = cp;
-
-       /* Initialize Port B IIC pins.
-       */
-       cp->cp_pbpar |= 0x00000030;
-       cp->cp_pbdir |= 0x00000030;
-       cp->cp_pbodr |= 0x00000030;
-
-       /* Allocate space for two transmit and two receive buffer
-        * descriptors in the DP ram.
-        */
-       data->dp_addr = cpm_dpalloc(sizeof(cbd_t) * 4, 8);
-               
-       /* ptr to i2c area */
-       data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c);
-}
-
-static int rpx_install_isr(int irq, void (*func)(void *), void *data)
-{
-       /* install interrupt handler */
-       cpm_install_handler(irq, func, data);
-
-       return 0;
-}
-
-static struct i2c_algo_8xx_data rpx_data = {
-       .setisr = rpx_install_isr
-};
-
-static struct i2c_adapter rpx_ops = {
-       .owner          = THIS_MODULE,
-       .name           = "m8xx",
-       .id             = I2C_HW_MPC8XX_EPON,
-       .algo_data      = &rpx_data,
-};
-
-int __init i2c_rpx_init(void)
-{
-       printk(KERN_INFO "i2c-rpx: i2c MPC8xx driver\n");
-
-       /* reset hardware to sane state */
-       rpx_iic_init(&rpx_data);
-
-       if (i2c_8xx_add_bus(&rpx_ops) < 0) {
-               printk(KERN_ERR "i2c-rpx: Unable to register with I2C\n");
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-void __exit i2c_rpx_exit(void)
-{
-       i2c_8xx_del_bus(&rpx_ops);
-}
-
-MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>");
-MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards");
-
-module_init(i2c_rpx_init);
-module_exit(i2c_rpx_exit);
index b7fb65c301124eb54e786bc5ef33153737028f06..8adf4abaa0352aff13ba7797456544459c27999f 100644 (file)
@@ -25,8 +25,6 @@
 /* This interfaces to the I2C bus of the Savage4 to gain access to
    the BT869 and possibly other I2C devices. The DDC bus is not
    yet supported because its register is not memory-mapped.
-   However we leave the DDC code here, commented out, to make
-   it easier to add later.
 */
 
 #include <linux/kernel.h>
 #include <linux/i2c-algo-bit.h>
 #include <asm/io.h>
 
-/* 3DFX defines */
-#define PCI_CHIP_SAVAGE3D      0x8A20
-#define PCI_CHIP_SAVAGE3D_MV   0x8A21
+/* device IDs */
 #define PCI_CHIP_SAVAGE4       0x8A22
 #define PCI_CHIP_SAVAGE2000    0x9102
-#define PCI_CHIP_PROSAVAGE_PM  0x8A25
-#define PCI_CHIP_PROSAVAGE_KM  0x8A26
-#define PCI_CHIP_SAVAGE_MX_MV  0x8c10
-#define PCI_CHIP_SAVAGE_MX     0x8c11
-#define PCI_CHIP_SAVAGE_IX_MV  0x8c12
-#define PCI_CHIP_SAVAGE_IX     0x8c13
 
 #define REG                    0xff20  /* Serial Port 1 Register */
 
 /* bit locations in the register */
-#define DDC_ENAB               0x00040000
-#define DDC_SCL_OUT            0x00080000
-#define DDC_SDA_OUT            0x00100000
-#define DDC_SCL_IN             0x00200000
-#define DDC_SDA_IN             0x00400000
 #define I2C_ENAB               0x00000020
 #define I2C_SCL_OUT            0x00000001
 #define I2C_SDA_OUT            0x00000002
 #define I2C_SCL_IN             0x00000008
 #define I2C_SDA_IN             0x00000010
 
-/* initialization states */
-#define INIT2                  0x20
-#define INIT3                  0x04
-
 /* delays */
 #define CYCLE_DELAY            10
 #define TIMEOUT                        (HZ / 2)
index a6feed449dbe65756ee0016e93fc1be5859dd4f4..283769cecee297531fd80c66e1cc34f1ee1bbf64 100644 (file)
@@ -129,6 +129,7 @@ MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller"
 
 static struct pci_driver sis5595_driver;
 static unsigned short sis5595_base;
+static struct pci_dev *sis5595_pdev;
 
 static u8 sis5595_read(u8 reg)
 {
@@ -379,6 +380,8 @@ MODULE_DEVICE_TABLE (pci, sis5595_ids);
 
 static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
+       int err;
+
        if (sis5595_setup(dev)) {
                dev_err(&dev->dev, "SIS5595 not detected, module not inserted.\n");
                return -ENODEV;
@@ -389,20 +392,24 @@ static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_
 
        sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
                sis5595_base + SMB_INDEX);
-       return i2c_add_adapter(&sis5595_adapter);
-}
+       err = i2c_add_adapter(&sis5595_adapter);
+       if (err) {
+               release_region(sis5595_base + SMB_INDEX, 2);
+               return err;
+       }
 
-static void __devexit sis5595_remove(struct pci_dev *dev)
-{
-       i2c_del_adapter(&sis5595_adapter);
-       release_region(sis5595_base + SMB_INDEX, 2);
+       /* Always return failure here.  This is to allow other drivers to bind
+        * to this pci device.  We don't really want to have control over the
+        * pci device, we only wanted to read as few register values from it.
+        */
+       sis5595_pdev =  pci_dev_get(dev);
+       return -ENODEV;
 }
 
 static struct pci_driver sis5595_driver = {
        .name           = "sis5595_smbus",
        .id_table       = sis5595_ids,
        .probe          = sis5595_probe,
-       .remove         = __devexit_p(sis5595_remove),
 };
 
 static int __init i2c_sis5595_init(void)
@@ -413,6 +420,12 @@ static int __init i2c_sis5595_init(void)
 static void __exit i2c_sis5595_exit(void)
 {
        pci_unregister_driver(&sis5595_driver);
+       if (sis5595_pdev) {
+               i2c_del_adapter(&sis5595_adapter);
+               release_region(sis5595_base + SMB_INDEX, 2);
+               pci_dev_put(sis5595_pdev);
+               sis5595_pdev = NULL;
+       }
 }
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c
new file mode 100644 (file)
index 0000000..1b0cfd5
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Driver for the TAOS evaluation modules
+ * These devices include an I2C master which can be controlled over the
+ * serial port.
+ *
+ * Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+
+#define TAOS_BUFFER_SIZE       63
+
+#define TAOS_STATE_INIT                0
+#define TAOS_STATE_IDLE                1
+#define TAOS_STATE_SEND                2
+#define TAOS_STATE_RECV                3
+
+#define TAOS_CMD_RESET         0x12
+
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+struct taos_data {
+       struct i2c_adapter adapter;
+       struct i2c_client *client;
+       int state;
+       u8 addr;                /* last used address */
+       unsigned char buffer[TAOS_BUFFER_SIZE];
+       unsigned int pos;       /* position inside the buffer */
+};
+
+/* TAOS TSL2550 EVM */
+static struct i2c_board_info tsl2550_info = {
+       I2C_BOARD_INFO("tsl2550", 0x39),
+       .type   = "tsl2550",
+};
+
+/* Instantiate i2c devices based on the adapter name */
+static struct i2c_client *taos_instantiate_device(struct i2c_adapter *adapter)
+{
+       if (!strncmp(adapter->name, "TAOS TSL2550 EVM", 16)) {
+               dev_info(&adapter->dev, "Instantiating device %s at 0x%02x\n",
+                       tsl2550_info.driver_name, tsl2550_info.addr);
+               return i2c_new_device(adapter, &tsl2550_info);
+       }
+
+       return NULL;
+}
+
+static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+                          unsigned short flags, char read_write, u8 command,
+                          int size, union i2c_smbus_data *data)
+{
+       struct serio *serio = adapter->algo_data;
+       struct taos_data *taos = serio_get_drvdata(serio);
+       char *p;
+
+       /* Encode our transaction. "@" is for the device address, "$" for the
+          SMBus command and "#" for the data. */
+       p = taos->buffer;
+
+       /* The device remembers the last used address, no need to send it
+          again if it's the same */
+       if (addr != taos->addr)
+               p += sprintf(p, "@%02X", addr);
+
+       switch (size) {
+       case I2C_SMBUS_BYTE:
+               if (read_write == I2C_SMBUS_WRITE)
+                       sprintf(p, "$#%02X", command);
+               else
+                       sprintf(p, "$");
+               break;
+       case I2C_SMBUS_BYTE_DATA:
+               if (read_write == I2C_SMBUS_WRITE)
+                       sprintf(p, "$%02X#%02X", command, data->byte);
+               else
+                       sprintf(p, "$%02X", command);
+               break;
+       default:
+               dev_dbg(&adapter->dev, "Unsupported transaction size %d\n",
+                       size);
+               return -EINVAL;
+       }
+
+       /* Send the transaction to the TAOS EVM */
+       dev_dbg(&adapter->dev, "Command buffer: %s\n", taos->buffer);
+       taos->pos = 0;
+       taos->state = TAOS_STATE_SEND;
+       serio_write(serio, taos->buffer[0]);
+       wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE,
+                                        msecs_to_jiffies(250));
+       if (taos->state != TAOS_STATE_IDLE) {
+               dev_err(&adapter->dev, "Transaction failed "
+                       "(state=%d, pos=%d)\n", taos->state, taos->pos);
+               taos->addr = 0;
+               return -EIO;
+       }
+       taos->addr = addr;
+
+       /* Start the transaction and read the answer */
+       taos->pos = 0;
+       taos->state = TAOS_STATE_RECV;
+       serio_write(serio, read_write == I2C_SMBUS_WRITE ? '>' : '<');
+       wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE,
+                                        msecs_to_jiffies(150));
+       if (taos->state != TAOS_STATE_IDLE
+        || taos->pos != 6) {
+               dev_err(&adapter->dev, "Transaction timeout (pos=%d)\n",
+                       taos->pos);
+               return -EIO;
+       }
+       dev_dbg(&adapter->dev, "Answer buffer: %s\n", taos->buffer);
+
+       /* Interpret the returned string */
+       p = taos->buffer + 2;
+       p[3] = '\0';
+       if (!strcmp(p, "NAK"))
+               return -ENODEV;
+
+       if (read_write == I2C_SMBUS_WRITE) {
+               if (!strcmp(p, "ACK"))
+                       return 0;
+       } else {
+               if (p[0] == 'x') {
+                       data->byte = simple_strtol(p + 1, NULL, 16);
+                       return 0;
+               }
+       }
+
+       return -EIO;
+}
+
+static u32 taos_smbus_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static const struct i2c_algorithm taos_algorithm = {
+       .smbus_xfer     = taos_smbus_xfer,
+       .functionality  = taos_smbus_func,
+};
+
+static irqreturn_t taos_interrupt(struct serio *serio, unsigned char data,
+                                 unsigned int flags)
+{
+       struct taos_data *taos = serio_get_drvdata(serio);
+
+       switch (taos->state) {
+       case TAOS_STATE_INIT:
+               taos->buffer[taos->pos++] = data;
+               if (data == ':'
+                || taos->pos == TAOS_BUFFER_SIZE - 1) {
+                       taos->buffer[taos->pos] = '\0';
+                       taos->state = TAOS_STATE_IDLE;
+                       wake_up_interruptible(&wq);
+               }
+               break;
+       case TAOS_STATE_SEND:
+               if (taos->buffer[++taos->pos])
+                       serio_write(serio, taos->buffer[taos->pos]);
+               else {
+                       taos->state = TAOS_STATE_IDLE;
+                       wake_up_interruptible(&wq);
+               }
+               break;
+       case TAOS_STATE_RECV:
+               taos->buffer[taos->pos++] = data;
+               if (data == ']') {
+                       taos->buffer[taos->pos] = '\0';
+                       taos->state = TAOS_STATE_IDLE;
+                       wake_up_interruptible(&wq);
+               }
+               break;
+       }
+
+       return IRQ_HANDLED;
+}
+
+/* Extract the adapter name from the buffer received after reset.
+   The buffer is modified and a pointer inside the buffer is returned. */
+static char *taos_adapter_name(char *buffer)
+{
+       char *start, *end;
+
+       start = strstr(buffer, "TAOS ");
+       if (!start)
+               return NULL;
+
+       end = strchr(start, '\r');
+       if (!end)
+               return NULL;
+       *end = '\0';
+
+       return start;
+}
+
+static int taos_connect(struct serio *serio, struct serio_driver *drv)
+{
+       struct taos_data *taos;
+       struct i2c_adapter *adapter;
+       char *name;
+       int err;
+
+       taos = kzalloc(sizeof(struct taos_data), GFP_KERNEL);
+       if (!taos) {
+               err = -ENOMEM;
+               goto exit;
+       }
+       taos->state = TAOS_STATE_INIT;
+       serio_set_drvdata(serio, taos);
+
+       err = serio_open(serio, drv);
+       if (err)
+               goto exit_kfree;
+
+       adapter = &taos->adapter;
+       adapter->owner = THIS_MODULE;
+       adapter->algo = &taos_algorithm;
+       adapter->algo_data = serio;
+       adapter->dev.parent = &serio->dev;
+
+       /* Reset the TAOS evaluation module to identify it */
+       serio_write(serio, TAOS_CMD_RESET);
+       wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE,
+                                        msecs_to_jiffies(2000));
+
+       if (taos->state != TAOS_STATE_IDLE) {
+               err = -ENODEV;
+               dev_dbg(&serio->dev, "TAOS EVM reset failed (state=%d, "
+                       "pos=%d)\n", taos->state, taos->pos);
+               goto exit_close;
+       }
+
+       name = taos_adapter_name(taos->buffer);
+       if (!name) {
+               err = -ENODEV;
+               dev_err(&serio->dev, "TAOS EVM identification failed\n");
+               goto exit_close;
+       }
+       strlcpy(adapter->name, name, sizeof(adapter->name));
+
+       err = i2c_add_adapter(adapter);
+       if (err)
+               goto exit_close;
+       dev_dbg(&serio->dev, "Connected to TAOS EVM\n");
+
+       taos->client = taos_instantiate_device(adapter);
+       return 0;
+
+ exit_close:
+       serio_close(serio);
+ exit_kfree:
+       serio_set_drvdata(serio, NULL);
+       kfree(taos);
+ exit:
+       return err;
+}
+
+static void taos_disconnect(struct serio *serio)
+{
+       struct taos_data *taos = serio_get_drvdata(serio);
+
+       if (taos->client)
+               i2c_unregister_device(taos->client);
+       i2c_del_adapter(&taos->adapter);
+       serio_close(serio);
+       serio_set_drvdata(serio, NULL);
+       kfree(taos);
+
+       dev_dbg(&serio->dev, "Disconnected from TAOS EVM\n");
+}
+
+static struct serio_device_id taos_serio_ids[] = {
+       {
+               .type   = SERIO_RS232,
+               .proto  = SERIO_TAOSEVM,
+               .id     = SERIO_ANY,
+               .extra  = SERIO_ANY,
+       },
+       { 0 }
+};
+MODULE_DEVICE_TABLE(serio, taos_serio_ids);
+
+static struct serio_driver taos_drv = {
+       .driver         = {
+               .name   = "taos-evm",
+       },
+       .description    = "TAOS evaluation module driver",
+       .id_table       = taos_serio_ids,
+       .connect        = taos_connect,
+       .disconnect     = taos_disconnect,
+       .interrupt      = taos_interrupt,
+};
+
+static int __init taos_init(void)
+{
+       return serio_register_driver(&taos_drv);
+}
+
+static void __exit taos_exit(void)
+{
+       serio_unregister_driver(&taos_drv);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("TAOS evaluation module driver");
+MODULE_LICENSE("GPL");
+
+module_init(taos_init);
+module_exit(taos_exit);
index 7a2bc06304fca779a3a5c2194d6d9d92e34a199c..edc275002f8087a2501251a37dc2c29e5b637838 100644 (file)
@@ -235,7 +235,7 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
                if (!(vt596_features & FEATURE_I2CBLOCK))
                        goto exit_unsupported;
                if (read_write == I2C_SMBUS_READ)
-                       outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
+                       outb_p(data->block[0], SMBHSTDAT0);
                /* Fall through */
        case I2C_SMBUS_BLOCK_DATA:
                outb_p(command, SMBHSTCMD);
@@ -397,8 +397,7 @@ found:
        case PCI_DEVICE_ID_VIA_82C686_4:
                /* The VT82C686B (rev 0x40) does support I2C block
                   transactions, but the VT82C686A (rev 0x30) doesn't */
-               if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
-                && temp >= 0x40)
+               if (pdev->revision >= 0x40)
                        vt596_features |= FEATURE_I2CBLOCK;
                break;
        }
index 0d6bd4f7b7fa6a782c53148f386dd623a6edc811..e6c4a2b762ec955497864f860815fb027d9aa275 100644 (file)
@@ -310,8 +310,6 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
                break;
 
        case I2C_SMBUS_I2C_BLOCK_DATA:
-               if (rw == I2C_SMBUS_READ)
-                       data->block[0] = I2C_SMBUS_BLOCK_MAX; /* For now */
                len = data->block[0];
                if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
                        return -EINVAL;
@@ -388,7 +386,7 @@ static const struct i2c_algorithm scx200_acb_algorithm = {
 };
 
 static struct scx200_acb_iface *scx200_acb_list;
-static DECLARE_MUTEX(scx200_acb_list_mutex);
+static DEFINE_MUTEX(scx200_acb_list_mutex);
 
 static __init int scx200_acb_probe(struct scx200_acb_iface *iface)
 {
@@ -472,10 +470,10 @@ static int __init scx200_acb_create(struct scx200_acb_iface *iface)
                return -ENODEV;
        }
 
-       down(&scx200_acb_list_mutex);
+       mutex_lock(&scx200_acb_list_mutex);
        iface->next = scx200_acb_list;
        scx200_acb_list = iface;
-       up(&scx200_acb_list_mutex);
+       mutex_unlock(&scx200_acb_list_mutex);
 
        return 0;
 }
@@ -633,10 +631,10 @@ static void __exit scx200_acb_cleanup(void)
 {
        struct scx200_acb_iface *iface;
 
-       down(&scx200_acb_list_mutex);
+       mutex_lock(&scx200_acb_list_mutex);
        while ((iface = scx200_acb_list) != NULL) {
                scx200_acb_list = iface->next;
-               up(&scx200_acb_list_mutex);
+               mutex_unlock(&scx200_acb_list_mutex);
 
                i2c_del_adapter(&iface->adapter);
 
@@ -648,9 +646,9 @@ static void __exit scx200_acb_cleanup(void)
                        release_region(iface->base, 8);
 
                kfree(iface);
-               down(&scx200_acb_list_mutex);
+               mutex_lock(&scx200_acb_list_mutex);
        }
-       up(&scx200_acb_list_mutex);
+       mutex_unlock(&scx200_acb_list_mutex);
 }
 
 module_init(scx200_acb_init);
index ea085a006eadd163318a9e68e79d9a8c8cc31627..3944e889cb219cb2dcbad8ee75603023f2893608 100644 (file)
@@ -5,7 +5,7 @@
 menu "Miscellaneous I2C Chip support"
 
 config SENSORS_DS1337
-       tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
+       tristate "Dallas DS1337 and DS1339 Real Time Clock (DEPRECATED)"
        depends on EXPERIMENTAL
        help
          If you say yes here you get support for Dallas Semiconductor
@@ -14,8 +14,11 @@ config SENSORS_DS1337
          This driver can also be built as a module.  If so, the module
          will be called ds1337.
 
+         This driver is deprecated and will be dropped soon. Use
+         rtc-ds1307 instead.
+
 config SENSORS_DS1374
-       tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
+       tristate "Dallas DS1374 Real Time Clock (DEPRECATED)"
        depends on EXPERIMENTAL
        help
          If you say yes here you get support for Dallas Semiconductor
@@ -24,6 +27,19 @@ config SENSORS_DS1374
          This driver can also be built as a module.  If so, the module
          will be called ds1374.
 
+         This driver is deprecated and will be dropped soon. Use
+         rtc-ds1374 instead.
+
+config DS1682
+       tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
+       depends on EXPERIMENTAL
+       help
+         If you say yes here you get support for Dallas Semiconductor
+         DS1682 Total Elapsed Time Recorder.
+
+         This driver can also be built as a module.  If so, the module
+         will be called ds1682.
+
 config SENSORS_EEPROM
        tristate "EEPROM reader"
        depends on EXPERIMENTAL
@@ -101,7 +117,7 @@ config TPS65010
          will be called tps65010.
 
 config SENSORS_M41T00
-       tristate "ST M41T00 RTC chip"
+       tristate "ST M41T00 RTC chip (DEPRECATED)"
        depends on PPC32
        help
          If you say yes here you get support for the ST M41T00 RTC chip.
@@ -109,6 +125,9 @@ config SENSORS_M41T00
          This driver can also be built as a module.  If so, the module
          will be called m41t00.
 
+         This driver is deprecated and will be dropped soon. Use
+         rtc-ds1307 or rtc-m41t80 instead.
+
 config SENSORS_MAX6875
        tristate "Maxim MAX6875 Power supply supervisor"
        depends on EXPERIMENTAL
@@ -124,4 +143,14 @@ config SENSORS_MAX6875
          This driver can also be built as a module.  If so, the module
          will be called max6875.
 
+config SENSORS_TSL2550
+       tristate "Taos TSL2550 ambient light sensor"
+       depends on EXPERIMENTAL
+       help
+         If you say yes here you get support for the Taos TSL2550
+         ambient light sensor.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tsl2550.
+
 endmenu
index 779868ef2e268c6a4520625acadcd21823ceb50b..d8cbeb3f4b634f6e76a4fe5fd4e0a0a3a1d26386 100644 (file)
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_SENSORS_DS1337)   += ds1337.o
 obj-$(CONFIG_SENSORS_DS1374)   += ds1374.o
+obj-$(CONFIG_DS1682)           += ds1682.o
 obj-$(CONFIG_SENSORS_EEPROM)   += eeprom.o
 obj-$(CONFIG_SENSORS_MAX6875)  += max6875.o
 obj-$(CONFIG_SENSORS_M41T00)   += m41t00.o
@@ -12,6 +13,7 @@ obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
 obj-$(CONFIG_SENSORS_PCF8591)  += pcf8591.o
 obj-$(CONFIG_ISP1301_OMAP)     += isp1301_omap.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
+obj-$(CONFIG_SENSORS_TSL2550)  += tsl2550.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/ds1682.c b/drivers/i2c/chips/ds1682.c
new file mode 100644 (file)
index 0000000..25fd467
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Dallas Semiconductor DS1682 Elapsed Time Recorder device driver
+ *
+ * Written by: Grant Likely <grant.likely@secretlab.ca>
+ *
+ * Copyright (C) 2007 Secret Lab Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * The DS1682 elapsed timer recorder is a simple device that implements
+ * one elapsed time counter, one event counter, an alarm signal and 10
+ * bytes of general purpose EEPROM.
+ *
+ * This driver provides access to the DS1682 counters and user data via
+ * the sysfs.  The following attributes are added to the device node:
+ *     elapsed_time (u32): Total elapsed event time in ms resolution
+ *     alarm_time (u32): When elapsed time exceeds the value in alarm_time,
+ *                       then the alarm pin is asserted.
+ *     event_count (u16): number of times the event pin has gone low.
+ *     eeprom (u8[10]): general purpose EEPROM
+ *
+ * Counter registers and user data are both read/write unless the device
+ * has been write protected.  This driver does not support turning off write
+ * protection.  Once write protection is turned on, it is impossible to
+ * turn it off again, so I have left the feature out of this driver to avoid
+ * accidental enabling, but it is trivial to add write protect support.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/sysfs.h>
+#include <linux/ctype.h>
+#include <linux/hwmon-sysfs.h>
+
+/* Device registers */
+#define DS1682_REG_CONFIG              0x00
+#define DS1682_REG_ALARM               0x01
+#define DS1682_REG_ELAPSED             0x05
+#define DS1682_REG_EVT_CNTR            0x09
+#define DS1682_REG_EEPROM              0x0b
+#define DS1682_REG_RESET               0x1d
+#define DS1682_REG_WRITE_DISABLE       0x1e
+#define DS1682_REG_WRITE_MEM_DISABLE   0x1f
+
+#define DS1682_EEPROM_SIZE             10
+
+/*
+ * Generic counter attributes
+ */
+static ssize_t ds1682_show(struct device *dev, struct device_attribute *attr,
+                          char *buf)
+{
+       struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+       struct i2c_client *client = to_i2c_client(dev);
+       __le32 val = 0;
+       int rc;
+
+       dev_dbg(dev, "ds1682_show() called on %s\n", attr->attr.name);
+
+       /* Read the register */
+       rc = i2c_smbus_read_i2c_block_data(client, sattr->index, sattr->nr,
+                                          (u8 *) & val);
+       if (rc < 0)
+               return -EIO;
+
+       /* Special case: the 32 bit regs are time values with 1/4s
+        * resolution, scale them up to milliseconds */
+       if (sattr->nr == 4)
+               return sprintf(buf, "%llu\n", ((u64) le32_to_cpu(val)) * 250);
+
+       /* Format the output string and return # of bytes */
+       return sprintf(buf, "%li\n", (long)le32_to_cpu(val));
+}
+
+static ssize_t ds1682_store(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+       struct i2c_client *client = to_i2c_client(dev);
+       char *endp;
+       u64 val;
+       __le32 val_le;
+       int rc;
+
+       dev_dbg(dev, "ds1682_store() called on %s\n", attr->attr.name);
+
+       /* Decode input */
+       val = simple_strtoull(buf, &endp, 0);
+       if (buf == endp) {
+               dev_dbg(dev, "input string not a number\n");
+               return -EINVAL;
+       }
+
+       /* Special case: the 32 bit regs are time values with 1/4s
+        * resolution, scale input down to quarter-seconds */
+       if (sattr->nr == 4)
+               do_div(val, 250);
+
+       /* write out the value */
+       val_le = cpu_to_le32(val);
+       rc = i2c_smbus_write_i2c_block_data(client, sattr->index, sattr->nr,
+                                           (u8 *) & val_le);
+       if (rc < 0) {
+               dev_err(dev, "register write failed; reg=0x%x, size=%i\n",
+                       sattr->index, sattr->nr);
+               return -EIO;
+       }
+
+       return count;
+}
+
+/*
+ * Simple register attributes
+ */
+static SENSOR_DEVICE_ATTR_2(elapsed_time, S_IRUGO | S_IWUSR, ds1682_show,
+                           ds1682_store, 4, DS1682_REG_ELAPSED);
+static SENSOR_DEVICE_ATTR_2(alarm_time, S_IRUGO | S_IWUSR, ds1682_show,
+                           ds1682_store, 4, DS1682_REG_ALARM);
+static SENSOR_DEVICE_ATTR_2(event_count, S_IRUGO | S_IWUSR, ds1682_show,
+                           ds1682_store, 2, DS1682_REG_EVT_CNTR);
+
+static const struct attribute_group ds1682_group = {
+       .attrs = (struct attribute *[]) {
+               &sensor_dev_attr_elapsed_time.dev_attr.attr,
+               &sensor_dev_attr_alarm_time.dev_attr.attr,
+               &sensor_dev_attr_event_count.dev_attr.attr,
+               NULL,
+       },
+};
+
+/*
+ * User data attribute
+ */
+static ssize_t ds1682_eeprom_read(struct kobject *kobj, char *buf, loff_t off,
+                                 size_t count)
+{
+       struct i2c_client *client = kobj_to_i2c_client(kobj);
+       int rc;
+
+       dev_dbg(&client->dev, "ds1682_eeprom_read(p=%p, off=%lli, c=%zi)\n",
+               buf, off, count);
+
+       if (off >= DS1682_EEPROM_SIZE)
+               return 0;
+
+       if (off + count > DS1682_EEPROM_SIZE)
+               count = DS1682_EEPROM_SIZE - off;
+
+       rc = i2c_smbus_read_i2c_block_data(client, DS1682_REG_EEPROM + off,
+                                          count, buf);
+       if (rc < 0)
+               return -EIO;
+
+       return count;
+}
+
+static ssize_t ds1682_eeprom_write(struct kobject *kobj, char *buf, loff_t off,
+                                  size_t count)
+{
+       struct i2c_client *client = kobj_to_i2c_client(kobj);
+
+       dev_dbg(&client->dev, "ds1682_eeprom_write(p=%p, off=%lli, c=%zi)\n",
+               buf, off, count);
+
+       if (off >= DS1682_EEPROM_SIZE)
+               return -ENOSPC;
+
+       if (off + count > DS1682_EEPROM_SIZE)
+               count = DS1682_EEPROM_SIZE - off;
+
+       /* Write out to the device */
+       if (i2c_smbus_write_i2c_block_data(client, DS1682_REG_EEPROM + off,
+                                          count, buf) < 0)
+               return -EIO;
+
+       return count;
+}
+
+static struct bin_attribute ds1682_eeprom_attr = {
+       .attr = {
+               .name = "eeprom",
+               .mode = S_IRUGO | S_IWUSR,
+               .owner = THIS_MODULE,
+       },
+       .size = DS1682_EEPROM_SIZE,
+       .read = ds1682_eeprom_read,
+       .write = ds1682_eeprom_write,
+};
+
+/*
+ * Called when a ds1682 device is matched with this driver
+ */
+static int ds1682_probe(struct i2c_client *client)
+{
+       int rc;
+
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_I2C_BLOCK)) {
+               dev_err(&client->dev, "i2c bus does not support the ds1682\n");
+               rc = -ENODEV;
+               goto exit;
+       }
+
+       rc = sysfs_create_group(&client->dev.kobj, &ds1682_group);
+       if (rc)
+               goto exit;
+
+       rc = sysfs_create_bin_file(&client->dev.kobj, &ds1682_eeprom_attr);
+       if (rc)
+               goto exit_bin_attr;
+
+       return 0;
+
+ exit_bin_attr:
+       sysfs_remove_group(&client->dev.kobj, &ds1682_group);
+ exit:
+       return rc;
+}
+
+static int ds1682_remove(struct i2c_client *client)
+{
+       sysfs_remove_bin_file(&client->dev.kobj, &ds1682_eeprom_attr);
+       sysfs_remove_group(&client->dev.kobj, &ds1682_group);
+       return 0;
+}
+
+static struct i2c_driver ds1682_driver = {
+       .driver = {
+               .name = "ds1682",
+       },
+       .probe = ds1682_probe,
+       .remove = ds1682_remove,
+};
+
+static int __init ds1682_init(void)
+{
+       return i2c_add_driver(&ds1682_driver);
+}
+
+static void __exit ds1682_exit(void)
+{
+       i2c_del_driver(&ds1682_driver);
+}
+
+MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
+MODULE_DESCRIPTION("DS1682 Elapsed Time Indicator driver");
+MODULE_LICENSE("GPL");
+
+module_init(ds1682_init);
+module_exit(ds1682_exit);
index bfce13c8f1ff764d9c6036a8b4cef9cb86cdf106..d3da1fb05b9bebe13d342f7d3a09fbbda585e58d 100644 (file)
@@ -88,8 +88,10 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
                dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
 
                if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
-                       for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_BLOCK_MAX)
-                               if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_BLOCK_MAX)
+                       for (i = slice << 5; i < (slice + 1) << 5; i += 32)
+                               if (i2c_smbus_read_i2c_block_data(client, i,
+                                                       32, data->data + i)
+                                                       != 32)
                                        goto exit;
                } else {
                        if (i2c_smbus_write_byte(client, slice << 5)) {
@@ -110,7 +112,8 @@ exit:
        mutex_unlock(&data->update_lock);
 }
 
-static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+                          char *buf, loff_t off, size_t count)
 {
        struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
        struct eeprom_data *data = i2c_get_clientdata(client);
@@ -143,7 +146,6 @@ static struct bin_attribute eeprom_attr = {
        .attr = {
                .name = "eeprom",
                .mode = S_IRUGO,
-               .owner = THIS_MODULE,
        },
        .size = EEPROM_SIZE,
        .read = eeprom_read,
index 76645c1429776e182b87e3d2578adc40222cffa1..64692f666372e374cacfeaedaab1bad5293b3e1f 100644 (file)
@@ -106,6 +106,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice)
                                            I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
                        if (i2c_smbus_read_i2c_block_data(client,
                                                          MAX6875_CMD_BLK_READ,
+                                                         SLICE_SIZE,
                                                          buf) != SLICE_SIZE) {
                                goto exit_up;
                        }
@@ -125,8 +126,9 @@ exit_up:
        mutex_unlock(&data->update_lock);
 }
 
-static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
-                           size_t count)
+static ssize_t max6875_read(struct kobject *kobj,
+                           struct bin_attribute *bin_attr,
+                           char *buf, loff_t off, size_t count)
 {
        struct i2c_client *client = kobj_to_i2c_client(kobj);
        struct max6875_data *data = i2c_get_clientdata(client);
@@ -152,7 +154,6 @@ static struct bin_attribute user_eeprom_attr = {
        .attr = {
                .name = "eeprom",
                .mode = S_IRUGO,
-               .owner = THIS_MODULE,
        },
        .size = USER_EEPROM_SIZE,
        .read = max6875_read,
diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c
new file mode 100644 (file)
index 0000000..3de4b19
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ *  tsl2550.c - Linux kernel modules for ambient light sensor
+ *
+ *  Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ *  Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#define TSL2550_DRV_NAME       "tsl2550"
+#define DRIVER_VERSION         "1.1.1"
+
+/*
+ * Defines
+ */
+
+#define TSL2550_POWER_DOWN             0x00
+#define TSL2550_POWER_UP               0x03
+#define TSL2550_STANDARD_RANGE         0x18
+#define TSL2550_EXTENDED_RANGE         0x1d
+#define TSL2550_READ_ADC0              0x43
+#define TSL2550_READ_ADC1              0x83
+
+/*
+ * Structs
+ */
+
+struct tsl2550_data {
+       struct i2c_client *client;
+       struct mutex update_lock;
+
+       unsigned int power_state : 1;
+       unsigned int operating_mode : 1;
+};
+
+/*
+ * Global data
+ */
+
+static const u8 TSL2550_MODE_RANGE[2] = {
+       TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE,
+};
+
+/*
+ * Management functions
+ */
+
+static int tsl2550_set_operating_mode(struct i2c_client *client, int mode)
+{
+       struct tsl2550_data *data = i2c_get_clientdata(client);
+
+       int ret = i2c_smbus_write_byte(client, TSL2550_MODE_RANGE[mode]);
+
+       data->operating_mode = mode;
+
+       return ret;
+}
+
+static int tsl2550_set_power_state(struct i2c_client *client, int state)
+{
+       struct tsl2550_data *data = i2c_get_clientdata(client);
+       int ret;
+
+       if (state == 0)
+               ret = i2c_smbus_write_byte(client, TSL2550_POWER_DOWN);
+       else {
+               ret = i2c_smbus_write_byte(client, TSL2550_POWER_UP);
+
+               /* On power up we should reset operating mode also... */
+               tsl2550_set_operating_mode(client, data->operating_mode);
+       }
+
+       data->power_state = state;
+
+       return ret;
+}
+
+static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd)
+{
+       unsigned long end;
+       int loop = 0, ret = 0;
+
+       /*
+        * Read ADC channel waiting at most 400ms (see data sheet for further
+        * info).
+        * To avoid long busy wait we spin for few milliseconds then
+        * start sleeping.
+        */
+       end = jiffies + msecs_to_jiffies(400);
+       while (time_before(jiffies, end)) {
+               i2c_smbus_write_byte(client, cmd);
+
+               if (loop++ < 5)
+                       mdelay(1);
+               else
+                       msleep(1);
+
+               ret = i2c_smbus_read_byte(client);
+               if (ret < 0)
+                       return ret;
+               else if (ret & 0x0080)
+                       break;
+       }
+       if (!(ret & 0x80))
+               return -EIO;
+       return ret & 0x7f;      /* remove the "valid" bit */
+}
+
+/*
+ * LUX calculation
+ */
+
+#define        TSL2550_MAX_LUX         1846
+
+static const u8 ratio_lut[] = {
+       100, 100, 100, 100, 100, 100, 100, 100,
+       100, 100, 100, 100, 100, 100, 99, 99,
+       99, 99, 99, 99, 99, 99, 99, 99,
+       99, 99, 99, 98, 98, 98, 98, 98,
+       98, 98, 97, 97, 97, 97, 97, 96,
+       96, 96, 96, 95, 95, 95, 94, 94,
+       93, 93, 93, 92, 92, 91, 91, 90,
+       89, 89, 88, 87, 87, 86, 85, 84,
+       83, 82, 81, 80, 79, 78, 77, 75,
+       74, 73, 71, 69, 68, 66, 64, 62,
+       60, 58, 56, 54, 52, 49, 47, 44,
+       42, 41, 40, 40, 39, 39, 38, 38,
+       37, 37, 37, 36, 36, 36, 35, 35,
+       35, 35, 34, 34, 34, 34, 33, 33,
+       33, 33, 32, 32, 32, 32, 32, 31,
+       31, 31, 31, 31, 30, 30, 30, 30,
+       30,
+};
+
+static const u16 count_lut[] = {
+       0, 1, 2, 3, 4, 5, 6, 7,
+       8, 9, 10, 11, 12, 13, 14, 15,
+       16, 18, 20, 22, 24, 26, 28, 30,
+       32, 34, 36, 38, 40, 42, 44, 46,
+       49, 53, 57, 61, 65, 69, 73, 77,
+       81, 85, 89, 93, 97, 101, 105, 109,
+       115, 123, 131, 139, 147, 155, 163, 171,
+       179, 187, 195, 203, 211, 219, 227, 235,
+       247, 263, 279, 295, 311, 327, 343, 359,
+       375, 391, 407, 423, 439, 455, 471, 487,
+       511, 543, 575, 607, 639, 671, 703, 735,
+       767, 799, 831, 863, 895, 927, 959, 991,
+       1039, 1103, 1167, 1231, 1295, 1359, 1423, 1487,
+       1551, 1615, 1679, 1743, 1807, 1871, 1935, 1999,
+       2095, 2223, 2351, 2479, 2607, 2735, 2863, 2991,
+       3119, 3247, 3375, 3503, 3631, 3759, 3887, 4015,
+};
+
+/*
+ * This function is described into Taos TSL2550 Designer's Notebook
+ * pages 2, 3.
+ */
+static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
+{
+       unsigned int lux;
+
+       /* Look up count from channel values */
+       u16 c0 = count_lut[ch0];
+       u16 c1 = count_lut[ch1];
+
+       /*
+        * Calculate ratio.
+        * Note: the "128" is a scaling factor
+        */
+       u8 r = 128;
+
+       /* Avoid division by 0 and count 1 cannot be greater than count 0 */
+       if (c0 && (c1 <= c0))
+               r = c1 * 128 / c0;
+       else
+               return -1;
+
+       /* Calculate LUX */
+       lux = ((c0 - c1) * ratio_lut[r]) / 256;
+
+       /* LUX range check */
+       return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
+}
+
+/*
+ * SysFS support
+ */
+
+static ssize_t tsl2550_show_power_state(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
+
+       return sprintf(buf, "%u\n", data->power_state);
+}
+
+static ssize_t tsl2550_store_power_state(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct tsl2550_data *data = i2c_get_clientdata(client);
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+       int ret;
+
+       if (val < 0 || val > 1)
+               return -EINVAL;
+
+       mutex_lock(&data->update_lock);
+       ret = tsl2550_set_power_state(client, val);
+       mutex_unlock(&data->update_lock);
+
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
+                  tsl2550_show_power_state, tsl2550_store_power_state);
+
+static ssize_t tsl2550_show_operating_mode(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
+
+       return sprintf(buf, "%u\n", data->operating_mode);
+}
+
+static ssize_t tsl2550_store_operating_mode(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct tsl2550_data *data = i2c_get_clientdata(client);
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+       int ret;
+
+       if (val < 0 || val > 1)
+               return -EINVAL;
+
+       if (data->power_state == 0)
+               return -EBUSY;
+
+       mutex_lock(&data->update_lock);
+       ret = tsl2550_set_operating_mode(client, val);
+       mutex_unlock(&data->update_lock);
+
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
+                  tsl2550_show_operating_mode, tsl2550_store_operating_mode);
+
+static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
+{
+       u8 ch0, ch1;
+       int ret;
+
+       ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC0);
+       if (ret < 0)
+               return ret;
+       ch0 = ret;
+
+       mdelay(1);
+
+       ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
+       if (ret < 0)
+               return ret;
+       ch1 = ret;
+
+       /* Do the job */
+       ret = tsl2550_calculate_lux(ch0, ch1);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t tsl2550_show_lux1_input(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct tsl2550_data *data = i2c_get_clientdata(client);
+       int ret;
+
+       /* No LUX data if not operational */
+       if (!data->power_state)
+               return -EBUSY;
+
+       mutex_lock(&data->update_lock);
+       ret = __tsl2550_show_lux(client, buf);
+       mutex_unlock(&data->update_lock);
+
+       return ret;
+}
+
+static DEVICE_ATTR(lux1_input, S_IRUGO,
+                  tsl2550_show_lux1_input, NULL);
+
+static struct attribute *tsl2550_attributes[] = {
+       &dev_attr_power_state.attr,
+       &dev_attr_operating_mode.attr,
+       &dev_attr_lux1_input.attr,
+       NULL
+};
+
+static const struct attribute_group tsl2550_attr_group = {
+       .attrs = tsl2550_attributes,
+};
+
+/*
+ * Initialization function
+ */
+
+static int tsl2550_init_client(struct i2c_client *client)
+{
+       struct tsl2550_data *data = i2c_get_clientdata(client);
+       int err;
+
+       /*
+        * Probe the chip. To do so we try to power up the device and then to
+        * read back the 0x03 code
+        */
+       err = i2c_smbus_write_byte(client, TSL2550_POWER_UP);
+       if (err < 0)
+               return err;
+       mdelay(1);
+       if (i2c_smbus_read_byte(client) != TSL2550_POWER_UP)
+               return -ENODEV;
+       data->power_state = 1;
+
+       /* Set the default operating mode */
+       err = i2c_smbus_write_byte(client,
+                                  TSL2550_MODE_RANGE[data->operating_mode]);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+
+static struct i2c_driver tsl2550_driver;
+static int __devinit tsl2550_probe(struct i2c_client *client)
+{
+       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct tsl2550_data *data;
+       int *opmode, err = 0;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) {
+               err = -EIO;
+               goto exit;
+       }
+
+       data = kzalloc(sizeof(struct tsl2550_data), GFP_KERNEL);
+       if (!data) {
+               err = -ENOMEM;
+               goto exit;
+       }
+       data->client = client;
+       i2c_set_clientdata(client, data);
+
+       /* Check platform data */
+       opmode = client->dev.platform_data;
+       if (opmode) {
+               if (*opmode < 0 || *opmode > 1) {
+                       dev_err(&client->dev, "invalid operating_mode (%d)\n",
+                                       *opmode);
+                       err = -EINVAL;
+                       goto exit_kfree;
+               }
+               data->operating_mode = *opmode;
+       } else
+               data->operating_mode = 0;       /* default mode is standard */
+       dev_info(&client->dev, "%s operating mode\n",
+                       data->operating_mode ? "extended" : "standard");
+
+       mutex_init(&data->update_lock);
+
+       /* Initialize the TSL2550 chip */
+       err = tsl2550_init_client(client);
+       if (err)
+               goto exit_kfree;
+
+       /* Register sysfs hooks */
+       err = sysfs_create_group(&client->dev.kobj, &tsl2550_attr_group);
+       if (err)
+               goto exit_kfree;
+
+       dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
+
+       return 0;
+
+exit_kfree:
+       kfree(data);
+exit:
+       return err;
+}
+
+static int __devexit tsl2550_remove(struct i2c_client *client)
+{
+       sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
+
+       /* Power down the device */
+       tsl2550_set_power_state(client, 0);
+
+       kfree(i2c_get_clientdata(client));
+
+       return 0;
+}
+
+static struct i2c_driver tsl2550_driver = {
+       .driver = {
+               .name   = TSL2550_DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .probe  = tsl2550_probe,
+       .remove = __devexit_p(tsl2550_remove),
+};
+
+static int __init tsl2550_init(void)
+{
+       return i2c_add_driver(&tsl2550_driver);
+}
+
+static void __exit tsl2550_exit(void)
+{
+       i2c_del_driver(&tsl2550_driver);
+}
+
+MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
+MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
+
+module_init(tsl2550_init);
+module_exit(tsl2550_exit);
index 435925eba437df0e3cf9cdc9896c3ca6fc97abe4..6971a62397db2cd581cf59b3e8d87e3f404aeb85 100644 (file)
@@ -207,6 +207,7 @@ EXPORT_SYMBOL_GPL(i2c_bus_type);
  * i2c_new_device - instantiate an i2c device for use with a new style driver
  * @adap: the adapter managing the device
  * @info: describes one I2C device; bus_num is ignored
+ * Context: can sleep
  *
  * Create a device to work with a new style i2c driver, where binding is
  * handled through driver model probe()/remove() methods.  This call is not
@@ -255,6 +256,7 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
 /**
  * i2c_unregister_device - reverse effect of i2c_new_device()
  * @client: value returned from i2c_new_device()
+ * Context: can sleep
  */
 void i2c_unregister_device(struct i2c_client *client)
 {
@@ -379,6 +381,7 @@ out_list:
 /**
  * i2c_add_adapter - declare i2c adapter, use dynamic bus number
  * @adapter: the adapter to add
+ * Context: can sleep
  *
  * This routine is used to declare an I2C adapter when its bus number
  * doesn't matter.  Examples: for I2C adapters dynamically added by
@@ -416,6 +419,7 @@ EXPORT_SYMBOL(i2c_add_adapter);
 /**
  * i2c_add_numbered_adapter - declare i2c adapter, use static bus number
  * @adap: the adapter to register (with adap->nr initialized)
+ * Context: can sleep
  *
  * This routine is used to declare an I2C adapter when its bus number
  * matters.  Example: for I2C adapters from system-on-chip CPUs, or
@@ -463,6 +467,14 @@ retry:
 }
 EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
 
+/**
+ * i2c_del_adapter - unregister I2C adapter
+ * @adap: the adapter being unregistered
+ * Context: can sleep
+ *
+ * This unregisters an I2C adapter which was previously registered
+ * by @i2c_add_adapter or @i2c_add_numbered_adapter.
+ */
 int i2c_del_adapter(struct i2c_adapter *adap)
 {
        struct list_head  *item, *_n;
@@ -598,6 +610,7 @@ EXPORT_SYMBOL(i2c_register_driver);
 /**
  * i2c_del_driver - unregister I2C driver
  * @driver: the driver being unregistered
+ * Context: can sleep
  */
 void i2c_del_driver(struct i2c_driver *driver)
 {
@@ -1331,10 +1344,14 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
 EXPORT_SYMBOL(i2c_smbus_write_block_data);
 
 /* Returns the number of read bytes */
-s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
+s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command,
+                                 u8 length, u8 *values)
 {
        union i2c_smbus_data data;
 
+       if (length > I2C_SMBUS_BLOCK_MAX)
+               length = I2C_SMBUS_BLOCK_MAX;
+       data.block[0] = length;
        if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
                              I2C_SMBUS_READ,command,
                              I2C_SMBUS_I2C_BLOCK_DATA,&data))
@@ -1455,7 +1472,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                break;
        case I2C_SMBUS_I2C_BLOCK_DATA:
                if (read_write == I2C_SMBUS_READ) {
-                       msg[1].len = I2C_SMBUS_BLOCK_MAX;
+                       msg[1].len = data->block[0];
                } else {
                        msg[0].len = data->block[0] + 1;
                        if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
@@ -1511,9 +1528,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                                data->word = msgbuf1[0] | (msgbuf1[1] << 8);
                                break;
                        case I2C_SMBUS_I2C_BLOCK_DATA:
-                               /* fixed at 32 for now */
-                               data->block[0] = I2C_SMBUS_BLOCK_MAX;
-                               for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
+                               for (i = 0; i < data->block[0]; i++)
                                        data->block[i+1] = msgbuf1[i];
                                break;
                        case I2C_SMBUS_BLOCK_DATA:
index e7a7097105923296482dcc37acef6a8bc53fddb9..64eee9551b2203f73654890921e766c4a7608c31 100644 (file)
@@ -283,6 +283,7 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
                    (data_arg.size != I2C_SMBUS_WORD_DATA) &&
                    (data_arg.size != I2C_SMBUS_PROC_CALL) &&
                    (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
+                   (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
                    (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
                    (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
                        dev_dbg(&client->adapter->dev,
@@ -329,10 +330,18 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
 
                if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
                    (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
+                   (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) ||
                    (data_arg.read_write == I2C_SMBUS_WRITE)) {
                        if (copy_from_user(&temp, data_arg.data, datasize))
                                return -EFAULT;
                }
+               if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
+                       /* Convert old I2C block commands to the new
+                          convention. This preserves binary compatibility. */
+                       data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA;
+                       if (data_arg.read_write == I2C_SMBUS_READ)
+                               temp.block[0] = I2C_SMBUS_BLOCK_MAX;
+               }
                res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
                      data_arg.read_write,
                      data_arg.command,data_arg.size,&temp);
index 7f4c0a5050a1393e27e0c2ec3c9e7117d0546935..8f2db8dd35f75f7875e3cac91cbf6303de086e19 100644 (file)
@@ -719,74 +719,25 @@ static int __init hd_init(void)
        device_timer.function = hd_times_out;
        blk_queue_hardsect_size(hd_queue, 512);
 
-#ifdef __i386__
        if (!NR_HD) {
-               extern struct drive_info drive_info;
-               unsigned char *BIOS = (unsigned char *) &drive_info;
-               unsigned long flags;
-               int cmos_disks;
-
-               for (drive=0 ; drive<2 ; drive++) {
-                       hd_info[drive].cyl = *(unsigned short *) BIOS;
-                       hd_info[drive].head = *(2+BIOS);
-                       hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
-                       hd_info[drive].ctl = *(8+BIOS);
-                       hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
-                       hd_info[drive].sect = *(14+BIOS);
-#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp
-                       if (hd_info[drive].cyl && NR_HD == drive)
-                               NR_HD++;
-#endif
-                       BIOS += 16;
-               }
-
-       /*
-               We query CMOS about hard disks : it could be that 
-               we have a SCSI/ESDI/etc controller that is BIOS
-               compatible with ST-506, and thus showing up in our
-               BIOS table, but not register compatible, and therefore
-               not present in CMOS.
-
-               Furthermore, we will assume that our ST-506 drives
-               <if any> are the primary drives in the system, and 
-               the ones reflected as drive 1 or 2.
-
-               The first drive is stored in the high nibble of CMOS
-               byte 0x12, the second in the low nibble.  This will be
-               either a 4 bit drive type or 0xf indicating use byte 0x19 
-               for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
-
-               Needless to say, a non-zero value means we have 
-               an AT controller hard disk for that drive.
-
-               Currently the rtc_lock is a bit academic since this
-               driver is non-modular, but someday... ?         Paul G.
-       */
-
-               spin_lock_irqsave(&rtc_lock, flags);
-               cmos_disks = CMOS_READ(0x12);
-               spin_unlock_irqrestore(&rtc_lock, flags);
-
-               if (cmos_disks & 0xf0) {
-                       if (cmos_disks & 0x0f)
-                               NR_HD = 2;
-                       else
-                               NR_HD = 1;
-               }
-       }
-#endif /* __i386__ */
-#ifdef __arm__
-       if (!NR_HD) {
-               /* We don't know anything about the drive.  This means
+               /*
+                * We don't know anything about the drive.  This means
                 * that you *MUST* specify the drive parameters to the
                 * kernel yourself.
+                *
+                * If we were on an i386, we used to read this info from
+                * the BIOS or CMOS.  This doesn't work all that well,
+                * since this assumes that this is a primary or secondary
+                * drive, and if we're using this legacy driver, it's
+                * probably an auxilliary controller added to recover
+                * legacy data off an ST-506 drive.  Either way, it's
+                * definitely safest to have the user explicitly specify
+                * the information.
                 */
                printk("hd: no drives specified - use hd=cyl,head,sectors"
                        " on kernel command line\n");
-       }
-#endif
-       if (!NR_HD)
                goto out;
+       }
 
        for (drive=0 ; drive < NR_HD ; drive++) {
                struct gendisk *disk = alloc_disk(64);
index 8a6b27b3bcc3fb67de4ebfdeb7305453a6ecf8de..ba0fb92b041770870dbfb5e49bdb0e2c28480f14 100644 (file)
@@ -508,7 +508,7 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
        u8 tmpbyte;
        struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0));
 
-       pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision);
+       m5229_revision = dev->revision;
 
        isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
 
index 84ed30cdb324de5d4928700807f8db1198140228..8d30b99a54d8cca8e9db1aad2cb719a16f3a6916 100644 (file)
@@ -123,8 +123,7 @@ static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count)
        amd_print("Driver Version:                     2.13");
        amd_print("South Bridge:                       %s", pci_name(bmide_dev));
 
-       pci_read_config_byte(dev, PCI_REVISION_ID, &t);
-       amd_print("Revision:                           IDE %#x", t);
+       amd_print("Revision:                           IDE %#x", dev->revision);
        amd_print("Highest DMA rate:                   UDMA%s", amd_dma[fls(amd_config->udma_mask) - 1]);
 
        amd_print("BM-DMA base:                        %#lx", amd_base);
@@ -312,8 +311,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
  */
 
        if (amd_config->flags & AMD_CHECK_SWDMA) {
-               pci_read_config_byte(dev, PCI_REVISION_ID, &t);
-               if (t <= 7)
+               if (dev->revision <= 7)
                        amd_config->flags |= AMD_BAD_SWDMA;
        }
 
@@ -383,7 +381,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
 
        pci_read_config_byte(dev, PCI_REVISION_ID, &t);
        printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
-               amd_chipset->name, pci_name(dev), t,
+               amd_chipset->name, pci_name(dev), dev->revision,
                amd_dma[fls(amd_config->udma_mask) - 1]);
 
 /*
index 8631b6c8aa15bbae16f1f1b6ad817eb76d353840..1e89dd6e5bbf9e0eb45d27132f89ba6d4805d776 100644 (file)
@@ -88,7 +88,6 @@ static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
        u8 reg72 = 0, reg73 = 0;                        /* primary */
        u8 reg7a = 0, reg7b = 0;                        /* secondary */
        u8 reg50 = 1, reg51 = 1, reg57 = 0, reg71 = 0;  /* extra */
-       u8 rev = 0;
 
        p += sprintf(p, "\nController: %d\n", index);
        p += sprintf(p, "PCI-%x Chipset.\n", dev->device);
@@ -103,9 +102,8 @@ static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
        (void) pci_read_config_byte(dev, UDIDETCR1, &reg7b);
 
        /* PCI0643/6 originally didn't have the primary channel enable bit */
-       (void) pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
        if ((dev->device == PCI_DEVICE_ID_CMD_643) ||
-           (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 3))
+           (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 3))
                reg51 |= CNTRL_ENA_1ST;
 
        p += sprintf(p, "---------------- Primary Channel "
@@ -604,14 +602,11 @@ static int __devinit init_setup_cmd64x(struct pci_dev *dev, ide_pci_device_t *d)
 
 static int __devinit init_setup_cmd646(struct pci_dev *dev, ide_pci_device_t *d)
 {
-       u8 rev = 0;
-
        /*
         * The original PCI0646 didn't have the primary channel enable bit,
         * it appeared starting with PCI0646U (i.e. revision ID 3).
         */
-       pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-       if (rev < 3)
+       if (dev->revision < 3)
                d->enablebits[0].reg = 0;
 
        return ide_setup_pci_device(dev, d);
index 1eec1f308d16f26955deb92a71588dd079cbd194..b5c00d15a70403ffdbc829c71d3b0ff4137c0d9b 100644 (file)
@@ -236,7 +236,7 @@ static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const ch
         */
 
        pci_set_master(cs5530_0);
-       pci_set_mwi(cs5530_0);
+       pci_try_set_mwi(cs5530_0);
 
        /*
         * Set PCI CacheLineSize to 16-bytes:
index 4b6bae8eee82822b875bd40f4ccba0cb72894c9b..e9b07a97c3408d1da2ac7cca57e268ed4173f3a6 100644 (file)
@@ -1413,11 +1413,9 @@ static int __devinit init_setup_hpt372n(struct pci_dev *dev, ide_pci_device_t *d
 static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
 {
        struct hpt_info *info;
-       u8 rev = 0, mcr1 = 0;
+       u8 mcr1 = 0;
 
-       pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
-       if (rev > 1) {
+       if (dev->revision > 1) {
                d->name = "HPT371N";
 
                info = &hpt371n;
@@ -1442,11 +1440,8 @@ static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
 static int __devinit init_setup_hpt372a(struct pci_dev *dev, ide_pci_device_t *d)
 {
        struct hpt_info *info;
-       u8 rev = 0;
-
-       pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
 
-       if (rev > 1) {
+       if (dev->revision > 1) {
                d->name = "HPT372N";
 
                info = &hpt372n;
@@ -1460,11 +1455,8 @@ static int __devinit init_setup_hpt372a(struct pci_dev *dev, ide_pci_device_t *d
 static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d)
 {
        struct hpt_info *info;
-       u8 rev = 0;
 
-       pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
-       if (rev > 1) {
+       if (dev->revision > 1) {
                d->name = "HPT302N";
 
                info = &hpt302n;
@@ -1478,7 +1470,7 @@ static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d)
 static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
 {
        struct pci_dev *dev2;
-       u8 rev = 0;
+       u8 rev = dev->revision;
        static char   *chipset_names[] = { "HPT366", "HPT366",  "HPT368",
                                           "HPT370", "HPT370A", "HPT372",
                                           "HPT372N" };
@@ -1489,8 +1481,6 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
        if (PCI_FUNC(dev->devfn) & 1)
                return -ENODEV;
 
-       pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
        switch (rev) {
        case 0:
        case 1:
index 2e0b29ef596a9a15039d43b04fb50566ba2a40ba..1372c35be035fcc898cb1fe708f8056c56079fde 100644 (file)
@@ -572,18 +572,16 @@ static void __devinit piix_check_450nx(void)
 {
        struct pci_dev *pdev = NULL;
        u16 cfg;
-       u8 rev;
        while((pdev=pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL)
        {
                /* Look for 450NX PXB. Check for problem configurations
                   A PCI quirk checks bit 6 already */
-               pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
                pci_read_config_word(pdev, 0x41, &cfg);
                /* Only on the original revision: IDE DMA can hang */
-               if(rev == 0x00)
+               if (pdev->revision == 0x00)
                        no_piix_dma = 1;
                /* On all revisions below 5 PXB bus lock must be disabled for IDE */
-               else if(cfg & (1<<14) && rev < 5)
+               else if (cfg & (1<<14) && pdev->revision < 5)
                        no_piix_dma = 2;
        }
        if(no_piix_dma)
index 1371b5bf6bf04b5537a7449fdcab0a0731465529..ed04e0c8dd4c491ae71f3f4b4821de6aa5e5ee97 100644 (file)
@@ -55,7 +55,6 @@ static const char *svwks_bad_ata100[] = {
        NULL
 };
 
-static u8 svwks_revision = 0;
 static struct pci_dev *isa_dev;
 
 static int check_in_drive_lists (ide_drive_t *drive, const char **list)
@@ -71,9 +70,6 @@ static u8 svwks_udma_filter(ide_drive_t *drive)
        struct pci_dev *dev     = HWIF(drive)->pci_dev;
        u8 mask = 0;
 
-       if (!svwks_revision)
-               pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
-
        if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
                return 0x1f;
        if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
@@ -88,9 +84,9 @@ static u8 svwks_udma_filter(ide_drive_t *drive)
                        return 0;
                /* Check the OSB4 DMA33 enable bit */
                return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0;
-       } else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) {
+       } else if (dev->revision < SVWKS_CSB5_REVISION_NEW) {
                return 0x07;
-       } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) {
+       } else if (dev->revision >= SVWKS_CSB5_REVISION_NEW) {
                u8 btr = 0, mode;
                pci_read_config_byte(dev, 0x5A, &btr);
                mode = btr & 0x3;
@@ -234,9 +230,6 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
        unsigned int reg;
        u8 btr;
 
-       /* save revision id to determine DMA capability */
-       pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
-
        /* force Master Latency Timer value to 64 PCICLKs */
        pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
 
@@ -315,7 +308,7 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
                if (!(PCI_FUNC(dev->devfn) & 1))
                        btr |= 0x2;
                else
-                       btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
+                       btr |= (dev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
                pci_write_config_byte(dev, 0x5A, btr);
        }
        /* Setup HT1000 SouthBridge Controller - Single Channel Only */
index f875183ac8d9bfef0b338c06f6e567852e856d79..756a9b6eb4624aa5688d3b2420a5dbde659a5977 100644 (file)
@@ -659,9 +659,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
 
                /* Special case for SiS630 : 630S/ET is ATA_100a */
                if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) {
-                       u8 hostrev;
-                       pci_read_config_byte(host, PCI_REVISION_ID, &hostrev);
-                       if (hostrev >= 0x30)
+                       if (host->revision >= 0x30)
                                chipset_family = ATA_100a;
                }
                pci_dev_put(host);
@@ -702,7 +700,6 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
                        u16 trueid;
                        u8 prefctl;
                        u8 idecfg;
-                       u8 sbrev;
 
                        pci_read_config_byte(dev, 0x4a, &idecfg);
                        pci_write_config_byte(dev, 0x4a, idecfg | 0x10);
@@ -712,11 +709,10 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
                        if (trueid == 0x5517) { /* SiS 961/961B */
 
                                lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */
-                               pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev);
                                pci_read_config_byte(dev, 0x49, &prefctl);
                                pci_dev_put(lpc_bridge);
 
-                               if (sbrev == 0x10 && (prefctl & 0x80)) {
+                               if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
                                        printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n");
                                        chipset_family = ATA_133a;
                                } else {
index 487879842af495959cbfcb92900c6bbe81f8f6e1..a7323d278c49ae15036941b13d3573a05116e273 100644 (file)
@@ -338,7 +338,6 @@ static void sl82c105_tune_drive(ide_drive_t *drive, u8 pio)
 static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
 {
        struct pci_dev *bridge;
-       u8 rev;
 
        /*
         * The bridge should be part of the same device, but function 0.
@@ -360,10 +359,9 @@ static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
        /*
         * We need to find function 0's revision, not function 1
         */
-       pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
        pci_dev_put(bridge);
 
-       return rev;
+       return bridge->revision;
 }
 
 /*
index d21dd2e7eeb3cbba63970a0bfc61768ed906207e..27e92fb9f95e0c49cdd1a874e017a8dc021a4f6a 100644 (file)
@@ -237,16 +237,14 @@ static int via82cxxx_ide_dma_check (ide_drive_t *drive)
 static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
 {
        struct via_isa_bridge *via_config;
-       u8 t;
 
        for (via_config = via_isa_bridges; via_config->id; via_config++)
                if ((*isa = pci_get_device(PCI_VENDOR_ID_VIA +
                        !!(via_config->flags & VIA_BAD_ID),
                        via_config->id, NULL))) {
 
-                       pci_read_config_byte(*isa, PCI_REVISION_ID, &t);
-                       if (t >= via_config->rev_min &&
-                           t <= via_config->rev_max)
+                       if ((*isa)->revision >= via_config->rev_min &&
+                           (*isa)->revision <= via_config->rev_max)
                                break;
                        pci_dev_put(*isa);
                }
@@ -404,10 +402,9 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
         * Print the boot message.
         */
 
-       pci_read_config_byte(isa, PCI_REVISION_ID, &t);
        printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %sDMA%s "
                "controller on pci%s\n",
-               via_config->name, t,
+               via_config->name, isa->revision,
                via_config->udma_mask ? "U" : "MW",
                via_dma[via_config->udma_mask ?
                        (fls(via_config->udma_mask) - 1) : 0],
index 994decc7bcf2afd9c2c129fb6556af935ad8ce73..a193dfbf99d2f38dd6c9066efb63daeaa14d3b1b 100644 (file)
@@ -1,14 +1,14 @@
-menu "InfiniBand support"
-       depends on HAS_IOMEM
-
-config INFINIBAND
-       depends on PCI || BROKEN
+menuconfig INFINIBAND
        tristate "InfiniBand support"
+       depends on PCI || BROKEN
+       depends on HAS_IOMEM
        ---help---
          Core support for InfiniBand (IB).  Make sure to also select
          any protocols you wish to use as well as drivers for your
          InfiniBand hardware.
 
+if INFINIBAND
+
 config INFINIBAND_USER_MAD
        tristate "InfiniBand userspace MAD support"
        depends on INFINIBAND
@@ -20,7 +20,6 @@ config INFINIBAND_USER_MAD
 
 config INFINIBAND_USER_ACCESS
        tristate "InfiniBand userspace access (verbs and CM)"
-       depends on INFINIBAND
        ---help---
          Userspace InfiniBand access support.  This enables the
          kernel side of userspace verbs and the userspace
@@ -37,7 +36,7 @@ config INFINIBAND_USER_MEM
 
 config INFINIBAND_ADDR_TRANS
        bool
-       depends on INFINIBAND && INET
+       depends on INET
        default y
 
 source "drivers/infiniband/hw/mthca/Kconfig"
@@ -54,4 +53,4 @@ source "drivers/infiniband/ulp/srp/Kconfig"
 
 source "drivers/infiniband/ulp/iser/Kconfig"
 
-endmenu
+endif # INFINIBAND
index ecd1a3057c61bf41e9f09c5be5727de78866620d..db2633e4aae6ec65b2bc49ecba6752a57b02650f 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (c) 2004, 2005 Infinicon Corporation.  All rights reserved.
  * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004, 2005 Topspin Corporation.  All rights reserved.
- * Copyright (c) 2004, 2005 Voltaire Corporation.  All rights reserved.
+ * Copyright (c) 2004-2007 Voltaire Corporation.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -34,7 +34,6 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: agent.c 1389 2004-12-27 22:56:47Z roland $
  */
 
 #include <linux/slab.h>
@@ -42,6 +41,7 @@
 
 #include "agent.h"
 #include "smi.h"
+#include "mad_priv.h"
 
 #define SPFX "ib_agent: "
 
@@ -87,8 +87,13 @@ int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
        struct ib_mad_send_buf *send_buf;
        struct ib_ah *ah;
        int ret;
+       struct ib_mad_send_wr_private *mad_send_wr;
+
+       if (device->node_type == RDMA_NODE_IB_SWITCH)
+               port_priv = ib_get_agent_port(device, 0);
+       else
+               port_priv = ib_get_agent_port(device, port_num);
 
-       port_priv = ib_get_agent_port(device, port_num);
        if (!port_priv) {
                printk(KERN_ERR SPFX "Unable to find port agent\n");
                return -ENODEV;
@@ -113,6 +118,14 @@ int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
 
        memcpy(send_buf->mad, mad, sizeof *mad);
        send_buf->ah = ah;
+
+       if (device->node_type == RDMA_NODE_IB_SWITCH) {
+               mad_send_wr = container_of(send_buf,
+                                          struct ib_mad_send_wr_private,
+                                          send_buf);
+               mad_send_wr->send_wr.wr.ud.port_num = port_num;
+       }
+
        if ((ret = ib_post_send_mad(send_buf, NULL))) {
                printk(KERN_ERR SPFX "ib_post_send_mad error:%d\n", ret);
                goto err2;
index 40c004a2697e62281c17380f32cfea619f0a9f95..9820c67ba47dd2566eaaac76cce25e5a0ebdc834 100644 (file)
@@ -87,6 +87,7 @@ struct cm_port {
 struct cm_device {
        struct list_head list;
        struct ib_device *device;
+       u8 ack_delay;
        struct cm_port port[0];
 };
 
@@ -95,7 +96,7 @@ struct cm_av {
        union ib_gid dgid;
        struct ib_ah_attr ah_attr;
        u16 pkey_index;
-       u8 packet_life_time;
+       u8 timeout;
 };
 
 struct cm_work {
@@ -154,6 +155,7 @@ struct cm_id_private {
        u8 retry_count;
        u8 rnr_retry_count;
        u8 service_timeout;
+       u8 target_ack_delay;
 
        struct list_head work_list;
        atomic_t work_count;
@@ -293,7 +295,7 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
        av->port = port;
        ib_init_ah_from_path(cm_dev->device, port->port_num, path,
                             &av->ah_attr);
-       av->packet_life_time = path->packet_life_time;
+       av->timeout = path->packet_life_time + 1;
        return 0;
 }
 
@@ -318,12 +320,10 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
 
 static void cm_free_id(__be32 local_id)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&cm.lock, flags);
+       spin_lock_irq(&cm.lock);
        idr_remove(&cm.local_id_table,
                   (__force int) (local_id ^ cm.random_id_operand));
-       spin_unlock_irqrestore(&cm.lock, flags);
+       spin_unlock_irq(&cm.lock);
 }
 
 static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
@@ -345,11 +345,10 @@ static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
 static struct cm_id_private * cm_acquire_id(__be32 local_id, __be32 remote_id)
 {
        struct cm_id_private *cm_id_priv;
-       unsigned long flags;
 
-       spin_lock_irqsave(&cm.lock, flags);
+       spin_lock_irq(&cm.lock);
        cm_id_priv = cm_get_id(local_id, remote_id);
-       spin_unlock_irqrestore(&cm.lock, flags);
+       spin_unlock_irq(&cm.lock);
 
        return cm_id_priv;
 }
@@ -646,6 +645,25 @@ static inline int cm_convert_to_ms(int iba_time)
        return 1 << max(iba_time - 8, 0);
 }
 
+/*
+ * calculate: 4.096x2^ack_timeout = 4.096x2^ack_delay + 2x4.096x2^life_time
+ * Because of how ack_timeout is stored, adding one doubles the timeout.
+ * To avoid large timeouts, select the max(ack_delay, life_time + 1), and
+ * increment it (round up) only if the other is within 50%.
+ */
+static u8 cm_ack_timeout(u8 ca_ack_delay, u8 packet_life_time)
+{
+       int ack_timeout = packet_life_time + 1;
+
+       if (ack_timeout >= ca_ack_delay)
+               ack_timeout += (ca_ack_delay >= (ack_timeout - 1));
+       else
+               ack_timeout = ca_ack_delay +
+                             (ack_timeout >= (ca_ack_delay - 1));
+
+       return min(31, ack_timeout);
+}
+
 static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info)
 {
        if (timewait_info->inserted_remote_id) {
@@ -689,7 +707,7 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv)
         * timewait before notifying the user that we've exited timewait.
         */
        cm_id_priv->id.state = IB_CM_TIMEWAIT;
-       wait_time = cm_convert_to_ms(cm_id_priv->av.packet_life_time + 1);
+       wait_time = cm_convert_to_ms(cm_id_priv->av.timeout);
        queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
                           msecs_to_jiffies(wait_time));
        cm_id_priv->timewait_info = NULL;
@@ -713,31 +731,30 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
 {
        struct cm_id_private *cm_id_priv;
        struct cm_work *work;
-       unsigned long flags;
 
        cm_id_priv = container_of(cm_id, struct cm_id_private, id);
 retest:
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        switch (cm_id->state) {
        case IB_CM_LISTEN:
                cm_id->state = IB_CM_IDLE;
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
-               spin_lock_irqsave(&cm.lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
+               spin_lock_irq(&cm.lock);
                rb_erase(&cm_id_priv->service_node, &cm.listen_service_table);
-               spin_unlock_irqrestore(&cm.lock, flags);
+               spin_unlock_irq(&cm.lock);
                break;
        case IB_CM_SIDR_REQ_SENT:
                cm_id->state = IB_CM_IDLE;
                ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                break;
        case IB_CM_SIDR_REQ_RCVD:
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
                break;
        case IB_CM_REQ_SENT:
                ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
                               &cm_id_priv->id.device->node_guid,
                               sizeof cm_id_priv->id.device->node_guid,
@@ -747,9 +764,9 @@ retest:
                if (err == -ENOMEM) {
                        /* Do not reject to allow future retries. */
                        cm_reset_to_idle(cm_id_priv);
-                       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+                       spin_unlock_irq(&cm_id_priv->lock);
                } else {
-                       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+                       spin_unlock_irq(&cm_id_priv->lock);
                        ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
                                       NULL, 0, NULL, 0);
                }
@@ -762,25 +779,25 @@ retest:
        case IB_CM_MRA_REQ_SENT:
        case IB_CM_REP_RCVD:
        case IB_CM_MRA_REP_SENT:
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
                               NULL, 0, NULL, 0);
                break;
        case IB_CM_ESTABLISHED:
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                ib_send_cm_dreq(cm_id, NULL, 0);
                goto retest;
        case IB_CM_DREQ_SENT:
                ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
                cm_enter_timewait(cm_id_priv);
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                break;
        case IB_CM_DREQ_RCVD:
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                ib_send_cm_drep(cm_id, NULL, 0);
                break;
        default:
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                break;
        }
 
@@ -912,7 +929,8 @@ static void cm_format_req(struct cm_req_msg *req_msg,
        cm_req_set_primary_sl(req_msg, param->primary_path->sl);
        cm_req_set_primary_subnet_local(req_msg, 1); /* local only... */
        cm_req_set_primary_local_ack_timeout(req_msg,
-               min(31, param->primary_path->packet_life_time + 1));
+               cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
+                              param->primary_path->packet_life_time));
 
        if (param->alternate_path) {
                req_msg->alt_local_lid = param->alternate_path->slid;
@@ -927,7 +945,8 @@ static void cm_format_req(struct cm_req_msg *req_msg,
                cm_req_set_alt_sl(req_msg, param->alternate_path->sl);
                cm_req_set_alt_subnet_local(req_msg, 1); /* local only... */
                cm_req_set_alt_local_ack_timeout(req_msg,
-                       min(31, param->alternate_path->packet_life_time + 1));
+                       cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
+                                      param->alternate_path->packet_life_time));
        }
 
        if (param->private_data && param->private_data_len)
@@ -1169,7 +1188,6 @@ static void cm_format_req_event(struct cm_work *work,
 static void cm_process_work(struct cm_id_private *cm_id_priv,
                            struct cm_work *work)
 {
-       unsigned long flags;
        int ret;
 
        /* We will typically only have the current event to report. */
@@ -1177,9 +1195,9 @@ static void cm_process_work(struct cm_id_private *cm_id_priv,
        cm_free_work(work);
 
        while (!ret && !atomic_add_negative(-1, &cm_id_priv->work_count)) {
-               spin_lock_irqsave(&cm_id_priv->lock, flags);
+               spin_lock_irq(&cm_id_priv->lock);
                work = cm_dequeue_work(cm_id_priv);
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                BUG_ON(!work);
                ret = cm_id_priv->id.cm_handler(&cm_id_priv->id,
                                                &work->cm_event);
@@ -1250,7 +1268,6 @@ static void cm_dup_req_handler(struct cm_work *work,
                               struct cm_id_private *cm_id_priv)
 {
        struct ib_mad_send_buf *msg = NULL;
-       unsigned long flags;
        int ret;
 
        /* Quick state check to discard duplicate REQs. */
@@ -1261,7 +1278,7 @@ static void cm_dup_req_handler(struct cm_work *work,
        if (ret)
                return;
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        switch (cm_id_priv->id.state) {
        case IB_CM_MRA_REQ_SENT:
                cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
@@ -1276,14 +1293,14 @@ static void cm_dup_req_handler(struct cm_work *work,
        default:
                goto unlock;
        }
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        ret = ib_post_send_mad(msg, NULL);
        if (ret)
                goto free;
        return;
 
-unlock:        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock:        spin_unlock_irq(&cm_id_priv->lock);
 free:  cm_free_msg(msg);
 }
 
@@ -1293,17 +1310,16 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
        struct cm_id_private *listen_cm_id_priv, *cur_cm_id_priv;
        struct cm_timewait_info *timewait_info;
        struct cm_req_msg *req_msg;
-       unsigned long flags;
 
        req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
 
        /* Check for possible duplicate REQ. */
-       spin_lock_irqsave(&cm.lock, flags);
+       spin_lock_irq(&cm.lock);
        timewait_info = cm_insert_remote_id(cm_id_priv->timewait_info);
        if (timewait_info) {
                cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
                                           timewait_info->work.remote_id);
-               spin_unlock_irqrestore(&cm.lock, flags);
+               spin_unlock_irq(&cm.lock);
                if (cur_cm_id_priv) {
                        cm_dup_req_handler(work, cur_cm_id_priv);
                        cm_deref_id(cur_cm_id_priv);
@@ -1315,7 +1331,7 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
        timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
        if (timewait_info) {
                cm_cleanup_timewait(cm_id_priv->timewait_info);
-               spin_unlock_irqrestore(&cm.lock, flags);
+               spin_unlock_irq(&cm.lock);
                cm_issue_rej(work->port, work->mad_recv_wc,
                             IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
                             NULL, 0);
@@ -1328,7 +1344,7 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
                                           req_msg->private_data);
        if (!listen_cm_id_priv) {
                cm_cleanup_timewait(cm_id_priv->timewait_info);
-               spin_unlock_irqrestore(&cm.lock, flags);
+               spin_unlock_irq(&cm.lock);
                cm_issue_rej(work->port, work->mad_recv_wc,
                             IB_CM_REJ_INVALID_SERVICE_ID, CM_MSG_RESPONSE_REQ,
                             NULL, 0);
@@ -1338,7 +1354,7 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
        atomic_inc(&cm_id_priv->refcount);
        cm_id_priv->id.state = IB_CM_REQ_RCVD;
        atomic_inc(&cm_id_priv->work_count);
-       spin_unlock_irqrestore(&cm.lock, flags);
+       spin_unlock_irq(&cm.lock);
 out:
        return listen_cm_id_priv;
 }
@@ -1440,7 +1456,8 @@ static void cm_format_rep(struct cm_rep_msg *rep_msg,
        cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn));
        rep_msg->resp_resources = param->responder_resources;
        rep_msg->initiator_depth = param->initiator_depth;
-       cm_rep_set_target_ack_delay(rep_msg, param->target_ack_delay);
+       cm_rep_set_target_ack_delay(rep_msg,
+                                   cm_id_priv->av.port->cm_dev->ack_delay);
        cm_rep_set_failover(rep_msg, param->failover_accepted);
        cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
        cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
@@ -1591,7 +1608,6 @@ static void cm_dup_rep_handler(struct cm_work *work)
        struct cm_id_private *cm_id_priv;
        struct cm_rep_msg *rep_msg;
        struct ib_mad_send_buf *msg = NULL;
-       unsigned long flags;
        int ret;
 
        rep_msg = (struct cm_rep_msg *) work->mad_recv_wc->recv_buf.mad;
@@ -1604,7 +1620,7 @@ static void cm_dup_rep_handler(struct cm_work *work)
        if (ret)
                goto deref;
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        if (cm_id_priv->id.state == IB_CM_ESTABLISHED)
                cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,
                              cm_id_priv->private_data,
@@ -1616,14 +1632,14 @@ static void cm_dup_rep_handler(struct cm_work *work)
                              cm_id_priv->private_data_len);
        else
                goto unlock;
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        ret = ib_post_send_mad(msg, NULL);
        if (ret)
                goto free;
        goto deref;
 
-unlock:        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock:        spin_unlock_irq(&cm_id_priv->lock);
 free:  cm_free_msg(msg);
 deref: cm_deref_id(cm_id_priv);
 }
@@ -1632,7 +1648,6 @@ static int cm_rep_handler(struct cm_work *work)
 {
        struct cm_id_private *cm_id_priv;
        struct cm_rep_msg *rep_msg;
-       unsigned long flags;
        int ret;
 
        rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -1644,13 +1659,13 @@ static int cm_rep_handler(struct cm_work *work)
 
        cm_format_rep_event(work);
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        switch (cm_id_priv->id.state) {
        case IB_CM_REQ_SENT:
        case IB_CM_MRA_REQ_RCVD:
                break;
        default:
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                ret = -EINVAL;
                goto error;
        }
@@ -1663,7 +1678,7 @@ static int cm_rep_handler(struct cm_work *work)
        /* Check for duplicate REP. */
        if (cm_insert_remote_id(cm_id_priv->timewait_info)) {
                spin_unlock(&cm.lock);
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                ret = -EINVAL;
                goto error;
        }
@@ -1673,7 +1688,7 @@ static int cm_rep_handler(struct cm_work *work)
                         &cm.remote_id_table);
                cm_id_priv->timewait_info->inserted_remote_id = 0;
                spin_unlock(&cm.lock);
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                cm_issue_rej(work->port, work->mad_recv_wc,
                             IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REP,
                             NULL, 0);
@@ -1689,6 +1704,13 @@ static int cm_rep_handler(struct cm_work *work)
        cm_id_priv->responder_resources = rep_msg->initiator_depth;
        cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg);
        cm_id_priv->rnr_retry_count = cm_rep_get_rnr_retry_count(rep_msg);
+       cm_id_priv->target_ack_delay = cm_rep_get_target_ack_delay(rep_msg);
+       cm_id_priv->av.timeout =
+                       cm_ack_timeout(cm_id_priv->target_ack_delay,
+                                      cm_id_priv->av.timeout - 1);
+       cm_id_priv->alt_av.timeout =
+                       cm_ack_timeout(cm_id_priv->target_ack_delay,
+                                      cm_id_priv->alt_av.timeout - 1);
 
        /* todo: handle peer_to_peer */
 
@@ -1696,7 +1718,7 @@ static int cm_rep_handler(struct cm_work *work)
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        if (ret)
                cm_process_work(cm_id_priv, work);
@@ -1712,7 +1734,6 @@ error:
 static int cm_establish_handler(struct cm_work *work)
 {
        struct cm_id_private *cm_id_priv;
-       unsigned long flags;
        int ret;
 
        /* See comment in cm_establish about lookup. */
@@ -1720,9 +1741,9 @@ static int cm_establish_handler(struct cm_work *work)
        if (!cm_id_priv)
                return -EINVAL;
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        if (cm_id_priv->id.state != IB_CM_ESTABLISHED) {
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                goto out;
        }
 
@@ -1730,7 +1751,7 @@ static int cm_establish_handler(struct cm_work *work)
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        if (ret)
                cm_process_work(cm_id_priv, work);
@@ -1746,7 +1767,6 @@ static int cm_rtu_handler(struct cm_work *work)
 {
        struct cm_id_private *cm_id_priv;
        struct cm_rtu_msg *rtu_msg;
-       unsigned long flags;
        int ret;
 
        rtu_msg = (struct cm_rtu_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -1757,10 +1777,10 @@ static int cm_rtu_handler(struct cm_work *work)
 
        work->cm_event.private_data = &rtu_msg->private_data;
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        if (cm_id_priv->id.state != IB_CM_REP_SENT &&
            cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) {
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                goto out;
        }
        cm_id_priv->id.state = IB_CM_ESTABLISHED;
@@ -1769,7 +1789,7 @@ static int cm_rtu_handler(struct cm_work *work)
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        if (ret)
                cm_process_work(cm_id_priv, work);
@@ -1932,7 +1952,6 @@ static int cm_dreq_handler(struct cm_work *work)
        struct cm_id_private *cm_id_priv;
        struct cm_dreq_msg *dreq_msg;
        struct ib_mad_send_buf *msg = NULL;
-       unsigned long flags;
        int ret;
 
        dreq_msg = (struct cm_dreq_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -1945,7 +1964,7 @@ static int cm_dreq_handler(struct cm_work *work)
 
        work->cm_event.private_data = &dreq_msg->private_data;
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        if (cm_id_priv->local_qpn != cm_dreq_get_remote_qpn(dreq_msg))
                goto unlock;
 
@@ -1964,7 +1983,7 @@ static int cm_dreq_handler(struct cm_work *work)
                cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv,
                               cm_id_priv->private_data,
                               cm_id_priv->private_data_len);
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
 
                if (ib_post_send_mad(msg, NULL))
                        cm_free_msg(msg);
@@ -1977,7 +1996,7 @@ static int cm_dreq_handler(struct cm_work *work)
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        if (ret)
                cm_process_work(cm_id_priv, work);
@@ -1985,7 +2004,7 @@ static int cm_dreq_handler(struct cm_work *work)
                cm_deref_id(cm_id_priv);
        return 0;
 
-unlock:        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock:        spin_unlock_irq(&cm_id_priv->lock);
 deref: cm_deref_id(cm_id_priv);
        return -EINVAL;
 }
@@ -1994,7 +2013,6 @@ static int cm_drep_handler(struct cm_work *work)
 {
        struct cm_id_private *cm_id_priv;
        struct cm_drep_msg *drep_msg;
-       unsigned long flags;
        int ret;
 
        drep_msg = (struct cm_drep_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2005,10 +2023,10 @@ static int cm_drep_handler(struct cm_work *work)
 
        work->cm_event.private_data = &drep_msg->private_data;
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        if (cm_id_priv->id.state != IB_CM_DREQ_SENT &&
            cm_id_priv->id.state != IB_CM_DREQ_RCVD) {
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                goto out;
        }
        cm_enter_timewait(cm_id_priv);
@@ -2017,7 +2035,7 @@ static int cm_drep_handler(struct cm_work *work)
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        if (ret)
                cm_process_work(cm_id_priv, work);
@@ -2107,17 +2125,16 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg)
 {
        struct cm_timewait_info *timewait_info;
        struct cm_id_private *cm_id_priv;
-       unsigned long flags;
        __be32 remote_id;
 
        remote_id = rej_msg->local_comm_id;
 
        if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_TIMEOUT) {
-               spin_lock_irqsave(&cm.lock, flags);
+               spin_lock_irq(&cm.lock);
                timewait_info = cm_find_remote_id( *((__be64 *) rej_msg->ari),
                                                  remote_id);
                if (!timewait_info) {
-                       spin_unlock_irqrestore(&cm.lock, flags);
+                       spin_unlock_irq(&cm.lock);
                        return NULL;
                }
                cm_id_priv = idr_find(&cm.local_id_table, (__force int)
@@ -2129,7 +2146,7 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg)
                        else
                                cm_id_priv = NULL;
                }
-               spin_unlock_irqrestore(&cm.lock, flags);
+               spin_unlock_irq(&cm.lock);
        } else if (cm_rej_get_msg_rejected(rej_msg) == CM_MSG_RESPONSE_REQ)
                cm_id_priv = cm_acquire_id(rej_msg->remote_comm_id, 0);
        else
@@ -2142,7 +2159,6 @@ static int cm_rej_handler(struct cm_work *work)
 {
        struct cm_id_private *cm_id_priv;
        struct cm_rej_msg *rej_msg;
-       unsigned long flags;
        int ret;
 
        rej_msg = (struct cm_rej_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2152,7 +2168,7 @@ static int cm_rej_handler(struct cm_work *work)
 
        cm_format_rej_event(work);
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        switch (cm_id_priv->id.state) {
        case IB_CM_REQ_SENT:
        case IB_CM_MRA_REQ_RCVD:
@@ -2176,7 +2192,7 @@ static int cm_rej_handler(struct cm_work *work)
                cm_enter_timewait(cm_id_priv);
                break;
        default:
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                ret = -EINVAL;
                goto out;
        }
@@ -2184,7 +2200,7 @@ static int cm_rej_handler(struct cm_work *work)
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        if (ret)
                cm_process_work(cm_id_priv, work);
@@ -2295,7 +2311,6 @@ static int cm_mra_handler(struct cm_work *work)
 {
        struct cm_id_private *cm_id_priv;
        struct cm_mra_msg *mra_msg;
-       unsigned long flags;
        int timeout, ret;
 
        mra_msg = (struct cm_mra_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2307,9 +2322,9 @@ static int cm_mra_handler(struct cm_work *work)
        work->cm_event.param.mra_rcvd.service_timeout =
                                        cm_mra_get_service_timeout(mra_msg);
        timeout = cm_convert_to_ms(cm_mra_get_service_timeout(mra_msg)) +
-                 cm_convert_to_ms(cm_id_priv->av.packet_life_time);
+                 cm_convert_to_ms(cm_id_priv->av.timeout);
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        switch (cm_id_priv->id.state) {
        case IB_CM_REQ_SENT:
                if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REQ ||
@@ -2342,7 +2357,7 @@ static int cm_mra_handler(struct cm_work *work)
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        if (ret)
                cm_process_work(cm_id_priv, work);
@@ -2350,7 +2365,7 @@ static int cm_mra_handler(struct cm_work *work)
                cm_deref_id(cm_id_priv);
        return 0;
 out:
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
        cm_deref_id(cm_id_priv);
        return -EINVAL;
 }
@@ -2379,7 +2394,8 @@ static void cm_format_lap(struct cm_lap_msg *lap_msg,
        cm_lap_set_sl(lap_msg, alternate_path->sl);
        cm_lap_set_subnet_local(lap_msg, 1); /* local only... */
        cm_lap_set_local_ack_timeout(lap_msg,
-               min(31, alternate_path->packet_life_time + 1));
+               cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
+                              alternate_path->packet_life_time));
 
        if (private_data && private_data_len)
                memcpy(lap_msg->private_data, private_data, private_data_len);
@@ -2410,6 +2426,9 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
        ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av);
        if (ret)
                goto out;
+       cm_id_priv->alt_av.timeout =
+                       cm_ack_timeout(cm_id_priv->target_ack_delay,
+                                      cm_id_priv->alt_av.timeout - 1);
 
        ret = cm_alloc_msg(cm_id_priv, &msg);
        if (ret)
@@ -2465,7 +2484,6 @@ static int cm_lap_handler(struct cm_work *work)
        struct cm_lap_msg *lap_msg;
        struct ib_cm_lap_event_param *param;
        struct ib_mad_send_buf *msg = NULL;
-       unsigned long flags;
        int ret;
 
        /* todo: verify LAP request and send reject APR if invalid. */
@@ -2480,7 +2498,7 @@ static int cm_lap_handler(struct cm_work *work)
        cm_format_path_from_lap(cm_id_priv, param->alternate_path, lap_msg);
        work->cm_event.private_data = &lap_msg->private_data;
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        if (cm_id_priv->id.state != IB_CM_ESTABLISHED)
                goto unlock;
 
@@ -2497,7 +2515,7 @@ static int cm_lap_handler(struct cm_work *work)
                              cm_id_priv->service_timeout,
                              cm_id_priv->private_data,
                              cm_id_priv->private_data_len);
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
 
                if (ib_post_send_mad(msg, NULL))
                        cm_free_msg(msg);
@@ -2515,7 +2533,7 @@ static int cm_lap_handler(struct cm_work *work)
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        if (ret)
                cm_process_work(cm_id_priv, work);
@@ -2523,7 +2541,7 @@ static int cm_lap_handler(struct cm_work *work)
                cm_deref_id(cm_id_priv);
        return 0;
 
-unlock:        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock:        spin_unlock_irq(&cm_id_priv->lock);
 deref: cm_deref_id(cm_id_priv);
        return -EINVAL;
 }
@@ -2598,7 +2616,6 @@ static int cm_apr_handler(struct cm_work *work)
 {
        struct cm_id_private *cm_id_priv;
        struct cm_apr_msg *apr_msg;
-       unsigned long flags;
        int ret;
 
        apr_msg = (struct cm_apr_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2612,11 +2629,11 @@ static int cm_apr_handler(struct cm_work *work)
        work->cm_event.param.apr_rcvd.info_len = apr_msg->info_length;
        work->cm_event.private_data = &apr_msg->private_data;
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        if (cm_id_priv->id.state != IB_CM_ESTABLISHED ||
            (cm_id_priv->id.lap_state != IB_CM_LAP_SENT &&
             cm_id_priv->id.lap_state != IB_CM_MRA_LAP_RCVD)) {
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                goto out;
        }
        cm_id_priv->id.lap_state = IB_CM_LAP_IDLE;
@@ -2626,7 +2643,7 @@ static int cm_apr_handler(struct cm_work *work)
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        if (ret)
                cm_process_work(cm_id_priv, work);
@@ -2761,7 +2778,6 @@ static int cm_sidr_req_handler(struct cm_work *work)
        struct cm_id_private *cm_id_priv, *cur_cm_id_priv;
        struct cm_sidr_req_msg *sidr_req_msg;
        struct ib_wc *wc;
-       unsigned long flags;
 
        cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
        if (IS_ERR(cm_id))
@@ -2778,27 +2794,26 @@ static int cm_sidr_req_handler(struct cm_work *work)
                                work->mad_recv_wc->recv_buf.grh,
                                &cm_id_priv->av);
        cm_id_priv->id.remote_id = sidr_req_msg->request_id;
-       cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
        cm_id_priv->tid = sidr_req_msg->hdr.tid;
        atomic_inc(&cm_id_priv->work_count);
 
-       spin_lock_irqsave(&cm.lock, flags);
+       spin_lock_irq(&cm.lock);
        cur_cm_id_priv = cm_insert_remote_sidr(cm_id_priv);
        if (cur_cm_id_priv) {
-               spin_unlock_irqrestore(&cm.lock, flags);
+               spin_unlock_irq(&cm.lock);
                goto out; /* Duplicate message. */
        }
+       cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
        cur_cm_id_priv = cm_find_listen(cm_id->device,
                                        sidr_req_msg->service_id,
                                        sidr_req_msg->private_data);
        if (!cur_cm_id_priv) {
-               rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
-               spin_unlock_irqrestore(&cm.lock, flags);
-               /* todo: reply with no match */
+               spin_unlock_irq(&cm.lock);
+               cm_reject_sidr_req(cm_id_priv, IB_SIDR_UNSUPPORTED);
                goto out; /* No match. */
        }
        atomic_inc(&cur_cm_id_priv->refcount);
-       spin_unlock_irqrestore(&cm.lock, flags);
+       spin_unlock_irq(&cm.lock);
 
        cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
        cm_id_priv->id.context = cur_cm_id_priv->id.context;
@@ -2899,7 +2914,6 @@ static int cm_sidr_rep_handler(struct cm_work *work)
 {
        struct cm_sidr_rep_msg *sidr_rep_msg;
        struct cm_id_private *cm_id_priv;
-       unsigned long flags;
 
        sidr_rep_msg = (struct cm_sidr_rep_msg *)
                                work->mad_recv_wc->recv_buf.mad;
@@ -2907,14 +2921,14 @@ static int cm_sidr_rep_handler(struct cm_work *work)
        if (!cm_id_priv)
                return -EINVAL; /* Unmatched reply. */
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        if (cm_id_priv->id.state != IB_CM_SIDR_REQ_SENT) {
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                goto out;
        }
        cm_id_priv->id.state = IB_CM_IDLE;
        ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        cm_format_sidr_rep_event(work);
        cm_process_work(cm_id_priv, work);
@@ -2930,14 +2944,13 @@ static void cm_process_send_error(struct ib_mad_send_buf *msg,
        struct cm_id_private *cm_id_priv;
        struct ib_cm_event cm_event;
        enum ib_cm_state state;
-       unsigned long flags;
        int ret;
 
        memset(&cm_event, 0, sizeof cm_event);
        cm_id_priv = msg->context[0];
 
        /* Discard old sends or ones without a response. */
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        state = (enum ib_cm_state) (unsigned long) msg->context[1];
        if (msg != cm_id_priv->msg || state != cm_id_priv->id.state)
                goto discard;
@@ -2964,7 +2977,7 @@ static void cm_process_send_error(struct ib_mad_send_buf *msg,
        default:
                goto discard;
        }
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
        cm_event.param.send_status = wc_status;
 
        /* No other events can occur on the cm_id at this point. */
@@ -2974,7 +2987,7 @@ static void cm_process_send_error(struct ib_mad_send_buf *msg,
                ib_destroy_cm_id(&cm_id_priv->id);
        return;
 discard:
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
        cm_free_msg(msg);
 }
 
@@ -3269,8 +3282,7 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
                        *qp_attr_mask |= IB_QP_ALT_PATH;
                        qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
                        qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
-                       qp_attr->alt_timeout =
-                                       cm_id_priv->alt_av.packet_life_time + 1;
+                       qp_attr->alt_timeout = cm_id_priv->alt_av.timeout;
                        qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
                }
                ret = 0;
@@ -3308,8 +3320,7 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
                                *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
                                                 IB_QP_RNR_RETRY |
                                                 IB_QP_MAX_QP_RD_ATOMIC;
-                               qp_attr->timeout =
-                                       cm_id_priv->av.packet_life_time + 1;
+                               qp_attr->timeout = cm_id_priv->av.timeout;
                                qp_attr->retry_cnt = cm_id_priv->retry_count;
                                qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
                                qp_attr->max_rd_atomic =
@@ -3323,8 +3334,7 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
                        *qp_attr_mask = IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE;
                        qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
                        qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
-                       qp_attr->alt_timeout =
-                               cm_id_priv->alt_av.packet_life_time + 1;
+                       qp_attr->alt_timeout = cm_id_priv->alt_av.timeout;
                        qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
                        qp_attr->path_mig_state = IB_MIG_REARM;
                }
@@ -3364,6 +3374,16 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
 }
 EXPORT_SYMBOL(ib_cm_init_qp_attr);
 
+void cm_get_ack_delay(struct cm_device *cm_dev)
+{
+       struct ib_device_attr attr;
+
+       if (ib_query_device(cm_dev->device, &attr))
+               cm_dev->ack_delay = 0; /* acks will rely on packet life time */
+       else
+               cm_dev->ack_delay = attr.local_ca_ack_delay;
+}
+
 static void cm_add_one(struct ib_device *device)
 {
        struct cm_device *cm_dev;
@@ -3388,6 +3408,7 @@ static void cm_add_one(struct ib_device *device)
                return;
 
        cm_dev->device = device;
+       cm_get_ack_delay(cm_dev);
 
        set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
        for (i = 1; i <= device->phys_port_cnt; i++) {
index 4d3aee90c249783bee765b3286b944e6c3abc426..aec9c7af825dd9ba2e3b5dc8c9f18f1026eb3dfb 100644 (file)
@@ -35,6 +35,7 @@
 #define CM_MSGS_H
 
 #include <rdma/ib_mad.h>
+#include <rdma/ib_cm.h>
 
 /*
  * Parameters to routines below should be in network-byte order, and values
index 32a0e66d2a235215bece711619ae36003660142d..23af7a032a035fbb1c082ca69fdc69053d026515 100644 (file)
@@ -2326,7 +2326,6 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
        rep.private_data_len = conn_param->private_data_len;
        rep.responder_resources = conn_param->responder_resources;
        rep.initiator_depth = conn_param->initiator_depth;
-       rep.target_ack_delay = CMA_CM_RESPONSE_TIMEOUT;
        rep.failover_accepted = 0;
        rep.flow_control = conn_param->flow_control;
        rep.rnr_retry_count = conn_param->rnr_retry_count;
index 85ccf13b8041353db8c43b6b5bd91d4efb17b446..6b8faca02f8a169c779d56f547e5308bb398930c 100644 (file)
@@ -675,10 +675,16 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
        struct ib_mad_port_private *port_priv;
        struct ib_mad_agent_private *recv_mad_agent = NULL;
        struct ib_device *device = mad_agent_priv->agent.device;
-       u8 port_num = mad_agent_priv->agent.port_num;
+       u8 port_num;
        struct ib_wc mad_wc;
        struct ib_send_wr *send_wr = &mad_send_wr->send_wr;
 
+       if (device->node_type == RDMA_NODE_IB_SWITCH &&
+           smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+               port_num = send_wr->wr.ud.port_num;
+       else
+               port_num = mad_agent_priv->agent.port_num;
+
        /*
         * Directed route handling starts if the initial LID routed part of
         * a request or the ending LID routed part of a response is empty.
@@ -1839,6 +1845,7 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv,
        struct ib_mad_private *recv, *response;
        struct ib_mad_list_head *mad_list;
        struct ib_mad_agent_private *mad_agent;
+       int port_num;
 
        response = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL);
        if (!response)
@@ -1872,25 +1879,50 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv,
        if (!validate_mad(&recv->mad.mad, qp_info->qp->qp_num))
                goto out;
 
+       if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH)
+               port_num = wc->port_num;
+       else
+               port_num = port_priv->port_num;
+
        if (recv->mad.mad.mad_hdr.mgmt_class ==
            IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+               enum smi_forward_action retsmi;
+
                if (smi_handle_dr_smp_recv(&recv->mad.smp,
                                           port_priv->device->node_type,
-                                          port_priv->port_num,
+                                          port_num,
                                           port_priv->device->phys_port_cnt) ==
                                           IB_SMI_DISCARD)
                        goto out;
 
-               if (smi_check_forward_dr_smp(&recv->mad.smp) == IB_SMI_LOCAL)
+               retsmi = smi_check_forward_dr_smp(&recv->mad.smp);
+               if (retsmi == IB_SMI_LOCAL)
                        goto local;
 
-               if (smi_handle_dr_smp_send(&recv->mad.smp,
-                                          port_priv->device->node_type,
-                                          port_priv->port_num) == IB_SMI_DISCARD)
-                       goto out;
+               if (retsmi == IB_SMI_SEND) { /* don't forward */
+                       if (smi_handle_dr_smp_send(&recv->mad.smp,
+                                                  port_priv->device->node_type,
+                                                  port_num) == IB_SMI_DISCARD)
+                               goto out;
+
+                       if (smi_check_local_smp(&recv->mad.smp, port_priv->device) == IB_SMI_DISCARD)
+                               goto out;
+               } else if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) {
+                       /* forward case for switches */
+                       memcpy(response, recv, sizeof(*response));
+                       response->header.recv_wc.wc = &response->header.wc;
+                       response->header.recv_wc.recv_buf.mad = &response->mad.mad;
+                       response->header.recv_wc.recv_buf.grh = &response->grh;
+
+                       if (!agent_send_response(&response->mad.mad,
+                                                &response->grh, wc,
+                                                port_priv->device,
+                                                smi_get_fwd_port(&recv->mad.smp),
+                                                qp_info->qp->qp_num))
+                               response = NULL;
 
-               if (smi_check_local_smp(&recv->mad.smp, port_priv->device) == IB_SMI_DISCARD)
                        goto out;
+               }
        }
 
 local:
@@ -1919,7 +1951,7 @@ local:
                                agent_send_response(&response->mad.mad,
                                                    &recv->grh, wc,
                                                    port_priv->device,
-                                                   port_priv->port_num,
+                                                   port_num,
                                                    qp_info->qp->qp_num);
                                goto out;
                        }
index 1e13ab42b70b5ceb382be0914cfd7bc34f904b4d..15b4c4d3606dbc4954d399e5ef0f1d5a5d254bb0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 Intel Corporation.  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 24c93fd320fb8716fb605c2c89afb9f9fd17ce6a..b1d4bbf4ce5c7f4fcc848b4cc98fd5fc007aa7f8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
  * Copyright (c) 2006 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 6469406ea9d82551fe8135cfdead567708ef347e..20ab6b3e484d517f29a21fa316f51e01681b30c7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
  * Copyright (c) 2006 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -56,6 +56,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 struct ib_sa_sm_ah {
        struct ib_ah        *ah;
        struct kref          ref;
+       u16                  pkey_index;
        u8                   src_path_mask;
 };
 
@@ -382,6 +383,13 @@ static void update_sm_ah(struct work_struct *work)
        kref_init(&new_ah->ref);
        new_ah->src_path_mask = (1 << port_attr.lmc) - 1;
 
+       new_ah->pkey_index = 0;
+       if (ib_find_pkey(port->agent->device, port->port_num,
+                        IB_DEFAULT_PKEY_FULL, &new_ah->pkey_index) &&
+           ib_find_pkey(port->agent->device, port->port_num,
+                        IB_DEFAULT_PKEY_PARTIAL, &new_ah->pkey_index))
+               printk(KERN_ERR "Couldn't find index for default PKey\n");
+
        memset(&ah_attr, 0, sizeof ah_attr);
        ah_attr.dlid     = port_attr.sm_lid;
        ah_attr.sl       = port_attr.sm_sl;
@@ -512,6 +520,35 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
 }
 EXPORT_SYMBOL(ib_init_ah_from_path);
 
+static int alloc_mad(struct ib_sa_query *query, gfp_t gfp_mask)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&query->port->ah_lock, flags);
+       kref_get(&query->port->sm_ah->ref);
+       query->sm_ah = query->port->sm_ah;
+       spin_unlock_irqrestore(&query->port->ah_lock, flags);
+
+       query->mad_buf = ib_create_send_mad(query->port->agent, 1,
+                                           query->sm_ah->pkey_index,
+                                           0, IB_MGMT_SA_HDR, IB_MGMT_SA_DATA,
+                                           gfp_mask);
+       if (!query->mad_buf) {
+               kref_put(&query->sm_ah->ref, free_sm_ah);
+               return -ENOMEM;
+       }
+
+       query->mad_buf->ah = query->sm_ah->ah;
+
+       return 0;
+}
+
+static void free_mad(struct ib_sa_query *query)
+{
+       ib_free_send_mad(query->mad_buf);
+       kref_put(&query->sm_ah->ref, free_sm_ah);
+}
+
 static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
 {
        unsigned long flags;
@@ -548,20 +585,11 @@ retry:
        query->mad_buf->context[0] = query;
        query->id = id;
 
-       spin_lock_irqsave(&query->port->ah_lock, flags);
-       kref_get(&query->port->sm_ah->ref);
-       query->sm_ah = query->port->sm_ah;
-       spin_unlock_irqrestore(&query->port->ah_lock, flags);
-
-       query->mad_buf->ah = query->sm_ah->ah;
-
        ret = ib_post_send_mad(query->mad_buf, NULL);
        if (ret) {
                spin_lock_irqsave(&idr_lock, flags);
                idr_remove(&query_idr, id);
                spin_unlock_irqrestore(&idr_lock, flags);
-
-               kref_put(&query->sm_ah->ref, free_sm_ah);
        }
 
        /*
@@ -647,13 +675,10 @@ int ib_sa_path_rec_get(struct ib_sa_client *client,
        if (!query)
                return -ENOMEM;
 
-       query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
-                                                    0, IB_MGMT_SA_HDR,
-                                                    IB_MGMT_SA_DATA, gfp_mask);
-       if (!query->sa_query.mad_buf) {
-               ret = -ENOMEM;
+       query->sa_query.port     = port;
+       ret = alloc_mad(&query->sa_query, gfp_mask);
+       if (ret)
                goto err1;
-       }
 
        ib_sa_client_get(client);
        query->sa_query.client = client;
@@ -665,7 +690,6 @@ int ib_sa_path_rec_get(struct ib_sa_client *client,
 
        query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
        query->sa_query.release  = ib_sa_path_rec_release;
-       query->sa_query.port     = port;
        mad->mad_hdr.method      = IB_MGMT_METHOD_GET;
        mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_PATH_REC);
        mad->sa_hdr.comp_mask    = comp_mask;
@@ -683,7 +707,7 @@ int ib_sa_path_rec_get(struct ib_sa_client *client,
 err2:
        *sa_query = NULL;
        ib_sa_client_put(query->sa_query.client);
-       ib_free_send_mad(query->sa_query.mad_buf);
+       free_mad(&query->sa_query);
 
 err1:
        kfree(query);
@@ -773,13 +797,10 @@ int ib_sa_service_rec_query(struct ib_sa_client *client,
        if (!query)
                return -ENOMEM;
 
-       query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
-                                                    0, IB_MGMT_SA_HDR,
-                                                    IB_MGMT_SA_DATA, gfp_mask);
-       if (!query->sa_query.mad_buf) {
-               ret = -ENOMEM;
+       query->sa_query.port     = port;
+       ret = alloc_mad(&query->sa_query, gfp_mask);
+       if (ret)
                goto err1;
-       }
 
        ib_sa_client_get(client);
        query->sa_query.client = client;
@@ -791,7 +812,6 @@ int ib_sa_service_rec_query(struct ib_sa_client *client,
 
        query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
        query->sa_query.release  = ib_sa_service_rec_release;
-       query->sa_query.port     = port;
        mad->mad_hdr.method      = method;
        mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
        mad->sa_hdr.comp_mask    = comp_mask;
@@ -810,7 +830,7 @@ int ib_sa_service_rec_query(struct ib_sa_client *client,
 err2:
        *sa_query = NULL;
        ib_sa_client_put(query->sa_query.client);
-       ib_free_send_mad(query->sa_query.mad_buf);
+       free_mad(&query->sa_query);
 
 err1:
        kfree(query);
@@ -869,13 +889,10 @@ int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
        if (!query)
                return -ENOMEM;
 
-       query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
-                                                    0, IB_MGMT_SA_HDR,
-                                                    IB_MGMT_SA_DATA, gfp_mask);
-       if (!query->sa_query.mad_buf) {
-               ret = -ENOMEM;
+       query->sa_query.port     = port;
+       ret = alloc_mad(&query->sa_query, gfp_mask);
+       if (ret)
                goto err1;
-       }
 
        ib_sa_client_get(client);
        query->sa_query.client = client;
@@ -887,7 +904,6 @@ int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
 
        query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
        query->sa_query.release  = ib_sa_mcmember_rec_release;
-       query->sa_query.port     = port;
        mad->mad_hdr.method      = method;
        mad->mad_hdr.attr_id     = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
        mad->sa_hdr.comp_mask    = comp_mask;
@@ -906,7 +922,7 @@ int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
 err2:
        *sa_query = NULL;
        ib_sa_client_put(query->sa_query.client);
-       ib_free_send_mad(query->sa_query.mad_buf);
+       free_mad(&query->sa_query);
 
 err1:
        kfree(query);
@@ -939,8 +955,7 @@ static void send_handler(struct ib_mad_agent *agent,
        idr_remove(&query_idr, query->id);
        spin_unlock_irqrestore(&idr_lock, flags);
 
-       ib_free_send_mad(mad_send_wc->send_buf);
-       kref_put(&query->sm_ah->ref, free_sm_ah);
+       free_mad(query);
        ib_sa_client_put(query->client);
        query->release(query);
 }
index 2bca753eb62276a7c49d52594e06c1a78ec6ba1a..87236753bce9b7a93f9b41b30297e7d4c5a4d432 100644 (file)
@@ -192,7 +192,7 @@ enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type,
                        }
                        /* smp->hop_ptr updated when sending */
                        return (node_type == RDMA_NODE_IB_SWITCH ?
-                               IB_SMI_HANDLE: IB_SMI_DISCARD);
+                               IB_SMI_HANDLE : IB_SMI_DISCARD);
                }
 
                /* C14-13:4 -- hop_ptr = 0 -> give to SM */
@@ -211,7 +211,7 @@ enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
        if (!ib_get_smp_direction(smp)) {
                /* C14-9:2 -- intermediate hop */
                if (hop_ptr && hop_ptr < hop_cnt)
-                       return IB_SMI_SEND;
+                       return IB_SMI_FORWARD;
 
                /* C14-9:3 -- at the end of the DR segment of path */
                if (hop_ptr == hop_cnt)
@@ -224,7 +224,7 @@ enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
        } else {
                /* C14-13:2  -- intermediate hop */
                if (2 <= hop_ptr && hop_ptr <= hop_cnt)
-                       return IB_SMI_SEND;
+                       return IB_SMI_FORWARD;
 
                /* C14-13:3 -- at the end of the DR segment of path */
                if (hop_ptr == 1)
@@ -233,3 +233,13 @@ enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
        }
        return IB_SMI_LOCAL;
 }
+
+/*
+ * Return the forwarding port number from initial_path for outgoing SMP and
+ * from return_path for returning SMP
+ */
+int smi_get_fwd_port(struct ib_smp *smp)
+{
+       return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] :
+               smp->return_path[smp->hop_ptr-1]);
+}
index 9a4b349efc307253baf3c44e843f0eabbf4fb215..1cfc2984434fe517e99c1004fe3fc6b5176c49bc 100644 (file)
@@ -48,10 +48,12 @@ enum smi_action {
 enum smi_forward_action {
        IB_SMI_LOCAL,   /* SMP should be completed up the stack */
        IB_SMI_SEND,    /* received DR SMP should be forwarded to the send queue */
+       IB_SMI_FORWARD  /* SMP should be forwarded (for switches only) */
 };
 
 enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type,
                                       int port_num, int phys_port_cnt);
+int smi_get_fwd_port(struct ib_smp *smp);
 extern enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp);
 extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
                                              u8 node_type, int port_num);
index 08c299ebf4a8b5da88872c9116782ce5dd91c3ec..70b77ae67422da6d1fc624a7dc1242a9cbe06af2 100644 (file)
@@ -311,7 +311,7 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
                return sprintf(buf, "N/A (no PMA)\n");
 
        in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
-       out_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+       out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
        if (!in_mad || !out_mad) {
                ret = -ENOMEM;
                goto out;
@@ -479,7 +479,6 @@ alloc_group_attrs(ssize_t (*show)(struct ib_port *,
 
                element->attr.attr.name  = element->name;
                element->attr.attr.mode  = S_IRUGO;
-               element->attr.attr.owner = THIS_MODULE;
                element->attr.show       = show;
                element->index           = i;
 
index 2586a3ee8eba6ae35c77a09460d3b9ea18e954fa..424983f5b1ee249f5685907d6f695c03c20d4c4a 100644 (file)
@@ -823,7 +823,6 @@ static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file,
        param.private_data_len    = cmd.len;
        param.responder_resources = cmd.responder_resources;
        param.initiator_depth     = cmd.initiator_depth;
-       param.target_ack_delay    = cmd.target_ack_delay;
        param.failover_accepted   = cmd.failover_accepted;
        param.flow_control        = cmd.flow_control;
        param.rnr_retry_count     = cmd.rnr_retry_count;
index d40652a801511b597b17de382c243d6d45adc3ef..26d0470eef6ec2c2a3abb706c821cc23437e26c1 100644 (file)
@@ -121,6 +121,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
 
        cur_base = addr & PAGE_MASK;
 
+       ret = 0;
        while (npages) {
                ret = get_user_pages(current, current->mm, cur_base,
                                     min_t(int, npages,
index 809cb14ac6deca2f6476e066e0cd290b546112bb..e6ce5f209e471ab8491a4c7ecacfa28a2532f979 100644 (file)
@@ -1,6 +1,6 @@
 config INFINIBAND_AMSO1100
        tristate "Ammasso 1100 HCA support"
-       depends on PCI && INET && INFINIBAND
+       depends on PCI && INET
        ---help---
          This is a low-level driver for the Ammasso 1100 host
          channel adapter (HCA).
index 77977f55dca3f4b55b3268aa3cd4a37b77a33ae6..2acec3fadf6951795b4f5c4122cae67234644e84 100644 (file)
@@ -1,6 +1,6 @@
 config INFINIBAND_CXGB3
        tristate "Chelsio RDMA Driver"
-       depends on CHELSIO_T3 && INFINIBAND && INET
+       depends on CHELSIO_T3 && INET
        select GENERIC_ALLOCATOR
        ---help---
          This is an iWARP/RDMA driver for the Chelsio T3 1GbE and
index 76049afc76554ef2a4c0487b348faca768dfc3d7..1518b41482ae017467faab19246805da98033414 100644 (file)
@@ -144,7 +144,7 @@ static int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev_p, u32 qpid)
        }
        wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));
        memset(wqe, 0, sizeof(*wqe));
-       build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 3, 1, qpid, 7);
+       build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 3, 0, qpid, 7);
        wqe->flags = cpu_to_be32(MODQP_WRITE_EC);
        sge_cmd = qpid << 8 | 3;
        wqe->sge_cmd = cpu_to_be64(sge_cmd);
@@ -548,7 +548,7 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
                        V_EC_UP_TOKEN(T3_CTL_QP_TID) | F_EC_VALID)) << 32;
        wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));
        memset(wqe, 0, sizeof(*wqe));
-       build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 0, 1,
+       build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 0, 0,
                       T3_CTL_QP_TID, 7);
        wqe->flags = cpu_to_be32(MODQP_WRITE_EC);
        sge_cmd = (3ULL << 56) | FW_RI_SGEEC_START << 8 | 3;
@@ -833,7 +833,7 @@ int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr)
        wqe->ird = cpu_to_be32(attr->ird);
        wqe->qp_dma_addr = cpu_to_be64(attr->qp_dma_addr);
        wqe->qp_dma_size = cpu_to_be32(attr->qp_dma_size);
-       wqe->rsvd = 0;
+       wqe->irs = cpu_to_be32(attr->irs);
        skb->priority = 0;      /* 0=>ToeQ; 1=>CtrlQ */
        return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb));
 }
index ff7290eacefb7ee83ec95565384a29891a06f91b..c84d4ac49355b3bc2f3d41f265b4e75c8cb568cf 100644 (file)
@@ -294,6 +294,7 @@ struct t3_rdma_init_attr {
        u64 qp_dma_addr;
        u32 qp_dma_size;
        u32 flags;
+       u32 irs;
 };
 
 struct t3_rdma_init_wr {
@@ -314,7 +315,7 @@ struct t3_rdma_init_wr {
        __be32 ird;
        __be64 qp_dma_addr;     /* 7 */
        __be32 qp_dma_size;     /* 8 */
-       u32 rsvd;
+       u32 irs;
 };
 
 struct t3_genbit {
index b2faff5abce8648f533211fec884d0fc04b8d19d..3b41dc0c39dd9c2da189273862ae5c1cf3362be3 100644 (file)
@@ -254,8 +254,6 @@ static void release_ep_resources(struct iwch_ep *ep)
        cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid);
        dst_release(ep->dst);
        l2t_release(L2DATA(ep->com.tdev), ep->l2t);
-       if (ep->com.tdev->type == T3B)
-               release_tid(ep->com.tdev, ep->hwtid, NULL);
        put_ep(&ep->com);
 }
 
@@ -515,7 +513,7 @@ static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb)
        req->len = htonl(len);
        req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
                           V_TX_SNDBUF(snd_win>>15));
-       req->flags = htonl(F_TX_IMM_ACK|F_TX_INIT);
+       req->flags = htonl(F_TX_INIT);
        req->sndseq = htonl(ep->snd_seq);
        BUG_ON(ep->mpa_skb);
        ep->mpa_skb = skb;
@@ -566,7 +564,7 @@ static int send_mpa_reject(struct iwch_ep *ep, const void *pdata, u8 plen)
        req->len = htonl(mpalen);
        req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
                           V_TX_SNDBUF(snd_win>>15));
-       req->flags = htonl(F_TX_IMM_ACK|F_TX_INIT);
+       req->flags = htonl(F_TX_INIT);
        req->sndseq = htonl(ep->snd_seq);
        BUG_ON(ep->mpa_skb);
        ep->mpa_skb = skb;
@@ -618,7 +616,7 @@ static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen)
        req->len = htonl(len);
        req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
                           V_TX_SNDBUF(snd_win>>15));
-       req->flags = htonl(F_TX_MORE | F_TX_IMM_ACK | F_TX_INIT);
+       req->flags = htonl(F_TX_INIT);
        req->sndseq = htonl(ep->snd_seq);
        ep->mpa_skb = skb;
        state_set(&ep->com, MPA_REP_SENT);
@@ -641,6 +639,7 @@ static int act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        cxgb3_insert_tid(ep->com.tdev, &t3c_client, ep, tid);
 
        ep->snd_seq = ntohl(req->snd_isn);
+       ep->rcv_seq = ntohl(req->rcv_isn);
 
        set_emss(ep, ntohs(req->tcp_opt));
 
@@ -1023,6 +1022,9 @@ static int rx_data(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        skb_pull(skb, sizeof(*hdr));
        skb_trim(skb, dlen);
 
+       ep->rcv_seq += dlen;
+       BUG_ON(ep->rcv_seq != (ntohl(hdr->seq) + dlen));
+
        switch (state_read(&ep->com)) {
        case MPA_REQ_SENT:
                process_mpa_reply(ep, skb);
@@ -1060,7 +1062,6 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        struct iwch_ep *ep = ctx;
        struct cpl_wr_ack *hdr = cplhdr(skb);
        unsigned int credits = ntohs(hdr->credits);
-       enum iwch_qp_attr_mask  mask;
 
        PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
 
@@ -1072,30 +1073,6 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        ep->mpa_skb = NULL;
        dst_confirm(ep->dst);
        if (state_read(&ep->com) == MPA_REP_SENT) {
-               struct iwch_qp_attributes attrs;
-
-               /* bind QP to EP and move to RTS */
-               attrs.mpa_attr = ep->mpa_attr;
-               attrs.max_ird = ep->ord;
-               attrs.max_ord = ep->ord;
-               attrs.llp_stream_handle = ep;
-               attrs.next_state = IWCH_QP_STATE_RTS;
-
-               /* bind QP and TID with INIT_WR */
-               mask = IWCH_QP_ATTR_NEXT_STATE |
-                                    IWCH_QP_ATTR_LLP_STREAM_HANDLE |
-                                    IWCH_QP_ATTR_MPA_ATTR |
-                                    IWCH_QP_ATTR_MAX_IRD |
-                                    IWCH_QP_ATTR_MAX_ORD;
-
-               ep->com.rpl_err = iwch_modify_qp(ep->com.qp->rhp,
-                                    ep->com.qp, mask, &attrs, 1);
-
-               if (!ep->com.rpl_err) {
-                       state_set(&ep->com, FPDU_MODE);
-                       established_upcall(ep);
-               }
-
                ep->com.rpl_done = 1;
                PDBG("waking up ep %p\n", ep);
                wake_up(&ep->com.waitq);
@@ -1124,6 +1101,15 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        return CPL_RET_BUF_DONE;
 }
 
+/*
+ * Return whether a failed active open has allocated a TID
+ */
+static inline int act_open_has_tid(int status)
+{
+       return status != CPL_ERR_TCAM_FULL && status != CPL_ERR_CONN_EXIST &&
+              status != CPL_ERR_ARP_MISS;
+}
+
 static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 {
        struct iwch_ep *ep = ctx;
@@ -1133,7 +1119,7 @@ static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
             status2errno(rpl->status));
        connect_reply_upcall(ep, status2errno(rpl->status));
        state_set(&ep->com, DEAD);
-       if (ep->com.tdev->type == T3B)
+       if (ep->com.tdev->type == T3B && act_open_has_tid(rpl->status))
                release_tid(ep->com.tdev, GET_TID(rpl), NULL);
        cxgb3_free_atid(ep->com.tdev, ep->atid);
        dst_release(ep->dst);
@@ -1378,6 +1364,7 @@ static int pass_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 
        PDBG("%s ep %p\n", __FUNCTION__, ep);
        ep->snd_seq = ntohl(req->snd_isn);
+       ep->rcv_seq = ntohl(req->rcv_isn);
 
        set_emss(ep, ntohs(req->tcp_opt));
 
@@ -1485,6 +1472,13 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        int ret;
        int state;
 
+       if (is_neg_adv_abort(req->status)) {
+               PDBG("%s neg_adv_abort ep %p tid %d\n", __FUNCTION__, ep,
+                    ep->hwtid);
+               t3_l2t_send_event(ep->com.tdev, ep->l2t);
+               return CPL_RET_BUF_DONE;
+       }
+
        /*
         * We get 2 peer aborts from the HW.  The first one must
         * be ignored except for scribbling that we need one more.
@@ -1494,13 +1488,6 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                return CPL_RET_BUF_DONE;
        }
 
-       if (is_neg_adv_abort(req->status)) {
-               PDBG("%s neg_adv_abort ep %p tid %d\n", __FUNCTION__, ep,
-                    ep->hwtid);
-               t3_l2t_send_event(ep->com.tdev, ep->l2t);
-               return CPL_RET_BUF_DONE;
-       }
-
        state = state_read(&ep->com);
        PDBG("%s ep %p state %u\n", __FUNCTION__, ep, state);
        switch (state) {
@@ -1732,10 +1719,8 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        struct iwch_qp *qp = get_qhp(h, conn_param->qpn);
 
        PDBG("%s ep %p tid %u\n", __FUNCTION__, ep, ep->hwtid);
-       if (state_read(&ep->com) == DEAD) {
-               put_ep(&ep->com);
+       if (state_read(&ep->com) == DEAD)
                return -ECONNRESET;
-       }
 
        BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
        BUG_ON(!qp);
@@ -1755,17 +1740,8 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        ep->ird = conn_param->ird;
        ep->ord = conn_param->ord;
        PDBG("%s %d ird %d ord %d\n", __FUNCTION__, __LINE__, ep->ird, ep->ord);
+
        get_ep(&ep->com);
-       err = send_mpa_reply(ep, conn_param->private_data,
-                            conn_param->private_data_len);
-       if (err) {
-               ep->com.cm_id = NULL;
-               ep->com.qp = NULL;
-               cm_id->rem_ref(cm_id);
-               abort_connection(ep, NULL, GFP_KERNEL);
-               put_ep(&ep->com);
-               return err;
-       }
 
        /* bind QP to EP and move to RTS */
        attrs.mpa_attr = ep->mpa_attr;
@@ -1783,16 +1759,28 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 
        err = iwch_modify_qp(ep->com.qp->rhp,
                             ep->com.qp, mask, &attrs, 1);
+       if (err)
+               goto err;
 
-       if (err) {
-               ep->com.cm_id = NULL;
-               ep->com.qp = NULL;
-               cm_id->rem_ref(cm_id);
-               abort_connection(ep, NULL, GFP_KERNEL);
-       } else {
-               state_set(&ep->com, FPDU_MODE);
-               established_upcall(ep);
-       }
+       err = send_mpa_reply(ep, conn_param->private_data,
+                            conn_param->private_data_len);
+       if (err)
+               goto err;
+
+       /* wait for wr_ack */
+       wait_event(ep->com.waitq, ep->com.rpl_done);
+       err = ep->com.rpl_err;
+       if (err)
+               goto err;
+
+       state_set(&ep->com, FPDU_MODE);
+       established_upcall(ep);
+       put_ep(&ep->com);
+       return 0;
+err:
+       ep->com.cm_id = NULL;
+       ep->com.qp = NULL;
+       cm_id->rem_ref(cm_id);
        put_ep(&ep->com);
        return err;
 }
index 21a388c313cffb536a2812fbc54a054480bd73f9..6107e7cd9b57dd54377c29601a473bbd8f24cc12 100644 (file)
@@ -175,6 +175,7 @@ struct iwch_ep {
        unsigned int atid;
        u32 hwtid;
        u32 snd_seq;
+       u32 rcv_seq;
        struct l2t_entry *l2t;
        struct dst_entry *dst;
        struct sk_buff *mpa_skb;
index e7c2c3948037e6853586be07e01f2c1f3b5731bb..f0c777589374cccf1af919534805675246e05f2c 100644 (file)
@@ -1163,9 +1163,10 @@ int iwch_register_device(struct iwch_dev *dev)
        dev->ibdev.post_recv = iwch_post_receive;
 
 
-       dev->ibdev.iwcm =
-           (struct iw_cm_verbs *) kmalloc(sizeof(struct iw_cm_verbs),
-                                          GFP_KERNEL);
+       dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
+       if (!dev->ibdev.iwcm)
+               return -ENOMEM;
+
        dev->ibdev.iwcm->connect = iwch_connect;
        dev->ibdev.iwcm->accept = iwch_accept_cr;
        dev->ibdev.iwcm->reject = iwch_reject_cr;
index 714dddbc9a987ec3ba6ac7633226d1e1cd831e1b..dd89b6b91f9c3f90ec564c7f95f3bdc9090aea75 100644 (file)
@@ -628,9 +628,9 @@ int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg)
        /* immediate data starts here. */
        term = (struct terminate_message *)wqe->send.sgl;
        build_term_codes(rsp_msg, &term->layer_etype, &term->ecode);
-       build_fw_riwrh((void *)wqe, T3_WR_SEND,
-                      T3_COMPLETION_FLAG | T3_NOTIFY_FLAG, 1,
-                      qhp->ep->hwtid, 5);
+       wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_SEND) |
+                        V_FW_RIWR_FLAGS(T3_COMPLETION_FLAG | T3_NOTIFY_FLAG));
+       wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid));
        skb->priority = CPL_PRIORITY_DATA;
        return cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb);
 }
@@ -732,6 +732,7 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
        init_attr.qp_dma_addr = qhp->wq.dma_addr;
        init_attr.qp_dma_size = (1UL << qhp->wq.size_log2);
        init_attr.flags = rqes_posted(qhp) ? RECVS_POSTED : 0;
+       init_attr.irs = qhp->ep->rcv_seq;
        PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
             "flags 0x%x qpcaps 0x%x\n", __FUNCTION__,
             init_attr.rq_addr, init_attr.rq_size,
index 1a854598e0e68d01ca4a4ede2bb765cc13e2dac5..59f807d8d58e5eb043fad41b7182bca53bac8cc5 100644 (file)
@@ -1,6 +1,6 @@
 config INFINIBAND_EHCA
        tristate "eHCA support"
-       depends on IBMEBUS && INFINIBAND
+       depends on IBMEBUS
        ---help---
        This driver supports the IBM pSeries eHCA InfiniBand adapter.
 
index 0d6e2c4bb2451f27f78dfea5aa191c1f66cebe58..3cd6bf3402d10c8a0d9d097b72d8fdf9b1bb5a11 100644 (file)
@@ -118,7 +118,7 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
                }
                memcpy(&av->av.grh.word_1, &gid, sizeof(gid));
        }
-       av->av.pmtu = EHCA_MAX_MTU;
+       av->av.pmtu = shca->max_mtu;
 
        /* dgid comes in grh.word_3 */
        memcpy(&av->av.grh.word_3, &ah_attr->grh.dgid,
@@ -137,6 +137,8 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
        struct ehca_av *av;
        struct ehca_ud_av new_ehca_av;
        struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+       struct ehca_shca *shca = container_of(ah->pd->device, struct ehca_shca,
+                                             ib_device);
        u32 cur_pid = current->tgid;
 
        if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
@@ -192,7 +194,7 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
                memcpy(&new_ehca_av.grh.word_1, &gid, sizeof(gid));
        }
 
-       new_ehca_av.pmtu = EHCA_MAX_MTU;
+       new_ehca_av.pmtu = shca->max_mtu;
 
        memcpy(&new_ehca_av.grh.word_3, &ah_attr->grh.dgid,
               sizeof(ah_attr->grh.dgid));
index 1d286d3cc2d5b05aa357e5ebd87015cace5a6bce..daf823ea1acedb242caa59e22b35de602570d1b5 100644 (file)
@@ -5,6 +5,7 @@
  *
  *  Authors: Heiko J Schick <schickhj@de.ibm.com>
  *           Christoph Raisch <raisch@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
  *
  *  Copyright (c) 2005 IBM Corporation
  *
@@ -86,11 +87,17 @@ struct ehca_eq {
        struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE];
 };
 
+struct ehca_sma_attr {
+       u16 lid, lmc, sm_sl, sm_lid;
+       u16 pkey_tbl_len, pkeys[16];
+};
+
 struct ehca_sport {
        struct ib_cq *ibcq_aqp1;
        struct ib_qp *ibqp_aqp1;
        enum ib_rate  rate;
        enum ib_port_state port_state;
+       struct ehca_sma_attr saved_attr;
 };
 
 struct ehca_shca {
@@ -107,6 +114,8 @@ struct ehca_shca {
        struct ehca_pd *pd;
        struct h_galpas galpas;
        struct mutex modify_mutex;
+       u64 hca_cap;
+       int max_mtu;
 };
 
 struct ehca_pd {
@@ -115,9 +124,20 @@ struct ehca_pd {
        u32 ownpid;
 };
 
+enum ehca_ext_qp_type {
+       EQPT_NORMAL    = 0,
+       EQPT_LLQP      = 1,
+       EQPT_SRQBASE   = 2,
+       EQPT_SRQ       = 3,
+};
+
 struct ehca_qp {
-       struct ib_qp ib_qp;
+       union {
+               struct ib_qp ib_qp;
+               struct ib_srq ib_srq;
+       };
        u32 qp_type;
+       enum ehca_ext_qp_type ext_type;
        struct ipz_queue ipz_squeue;
        struct ipz_queue ipz_rqueue;
        struct h_galpas galpas;
@@ -140,6 +160,10 @@ struct ehca_qp {
        u32 mm_count_galpa;
 };
 
+#define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
+#define HAS_SQ(qp) (qp->ext_type != EQPT_SRQ)
+#define HAS_RQ(qp) (qp->ext_type != EQPT_SRQBASE)
+
 /* must be power of 2 */
 #define QP_HASHTAB_LEN 8
 
@@ -156,8 +180,8 @@ struct ehca_cq {
        spinlock_t cb_lock;
        struct hlist_head qp_hashtab[QP_HASHTAB_LEN];
        struct list_head entry;
-       u32 nr_callbacks; /* #events assigned to cpu by scaling code */
-       u32 nr_events;    /* #events seen */
+       u32 nr_callbacks;   /* #events assigned to cpu by scaling code */
+       atomic_t nr_events; /* #events seen */
        wait_queue_head_t wait_completion;
        spinlock_t task_lock;
        u32 ownpid;
@@ -275,9 +299,8 @@ void ehca_cleanup_av_cache(void);
 int ehca_init_mrmw_cache(void);
 void ehca_cleanup_mrmw_cache(void);
 
-extern spinlock_t ehca_qp_idr_lock;
-extern spinlock_t ehca_cq_idr_lock;
-extern spinlock_t hcall_lock;
+extern rwlock_t ehca_qp_idr_lock;
+extern rwlock_t ehca_cq_idr_lock;
 extern struct idr ehca_qp_idr;
 extern struct idr ehca_cq_idr;
 
@@ -305,6 +328,7 @@ struct ehca_create_qp_resp {
        u32 qp_num;
        u32 token;
        u32 qp_type;
+       u32 ext_type;
        u32 qkey;
        /* qp_num assigned by ehca: sqp0/1 may have got different numbers */
        u32 real_qp_num;
@@ -320,14 +344,42 @@ struct ehca_alloc_cq_parms {
        struct ipz_eq_handle eq_handle;
 };
 
+enum ehca_service_type {
+       ST_RC  = 0,
+       ST_UC  = 1,
+       ST_RD  = 2,
+       ST_UD  = 3,
+};
+
+enum ehca_ll_comp_flags {
+       LLQP_SEND_COMP = 0x20,
+       LLQP_RECV_COMP = 0x40,
+       LLQP_COMP_MASK = 0x60,
+};
+
 struct ehca_alloc_qp_parms {
-       int servicetype;
+/* input parameters */
+       enum ehca_service_type servicetype;
        int sigtype;
-       int daqp_ctrl;
-       int max_send_sge;
-       int max_recv_sge;
+       enum ehca_ext_qp_type ext_type;
+       enum ehca_ll_comp_flags ll_comp_flags;
+
+       int max_send_wr, max_recv_wr;
+       int max_send_sge, max_recv_sge;
        int ud_av_l_key_ctl;
 
+       u32 token;
+       struct ipz_eq_handle eq_handle;
+       struct ipz_pd pd;
+       struct ipz_cq_handle send_cq_handle, recv_cq_handle;
+
+       u32 srq_qpn, srq_token, srq_limit;
+
+/* output parameters */
+       u32 real_qp_num;
+       struct ipz_qp_handle qp_handle;
+       struct h_galpas galpas;
+
        u16 act_nr_send_wqes;
        u16 act_nr_recv_wqes;
        u8  act_nr_recv_sges;
@@ -335,9 +387,6 @@ struct ehca_alloc_qp_parms {
 
        u32 nr_rq_pages;
        u32 nr_sq_pages;
-
-       struct ipz_eq_handle ipz_eq_handle;
-       struct ipz_pd pd;
 };
 
 int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp);
index 5665f213b81a2ec11309ad0d8a9d0bddf0a4a785..fb3df5c271e7e144d5ffb344296ba9a9a775adab 100644 (file)
@@ -228,8 +228,8 @@ struct hcp_modify_qp_control_block {
 #define MQPCB_QP_NUMBER                         EHCA_BMASK_IBM(8,31)
 #define MQPCB_MASK_QP_ENABLE                    EHCA_BMASK_IBM(48,48)
 #define MQPCB_QP_ENABLE                         EHCA_BMASK_IBM(31,31)
-#define MQPCB_MASK_CURR_SQR_LIMIT               EHCA_BMASK_IBM(49,49)
-#define MQPCB_CURR_SQR_LIMIT                    EHCA_BMASK_IBM(15,31)
+#define MQPCB_MASK_CURR_SRQ_LIMIT               EHCA_BMASK_IBM(49,49)
+#define MQPCB_CURR_SRQ_LIMIT                    EHCA_BMASK_IBM(16,31)
 #define MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG       EHCA_BMASK_IBM(50,50)
 #define MQPCB_MASK_SHARED_RQ_HNDL               EHCA_BMASK_IBM(51,51)
 
index 67f0670fe3b18624cd752a9ed01b65a660165d81..01d4a148bd719c4cd955c0628034b97cc14543d8 100644 (file)
@@ -56,11 +56,11 @@ int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp)
 {
        unsigned int qp_num = qp->real_qp_num;
        unsigned int key = qp_num & (QP_HASHTAB_LEN-1);
-       unsigned long spl_flags;
+       unsigned long flags;
 
-       spin_lock_irqsave(&cq->spinlock, spl_flags);
+       spin_lock_irqsave(&cq->spinlock, flags);
        hlist_add_head(&qp->list_entries, &cq->qp_hashtab[key]);
-       spin_unlock_irqrestore(&cq->spinlock, spl_flags);
+       spin_unlock_irqrestore(&cq->spinlock, flags);
 
        ehca_dbg(cq->ib_cq.device, "cq_num=%x real_qp_num=%x",
                 cq->cq_number, qp_num);
@@ -74,9 +74,9 @@ int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num)
        unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1);
        struct hlist_node *iter;
        struct ehca_qp *qp;
-       unsigned long spl_flags;
+       unsigned long flags;
 
-       spin_lock_irqsave(&cq->spinlock, spl_flags);
+       spin_lock_irqsave(&cq->spinlock, flags);
        hlist_for_each(iter, &cq->qp_hashtab[key]) {
                qp = hlist_entry(iter, struct ehca_qp, list_entries);
                if (qp->real_qp_num == real_qp_num) {
@@ -88,7 +88,7 @@ int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num)
                        break;
                }
        }
-       spin_unlock_irqrestore(&cq->spinlock, spl_flags);
+       spin_unlock_irqrestore(&cq->spinlock, flags);
        if (ret)
                ehca_err(cq->ib_cq.device,
                         "qp not found cq_num=%x real_qp_num=%x",
@@ -146,6 +146,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
        spin_lock_init(&my_cq->spinlock);
        spin_lock_init(&my_cq->cb_lock);
        spin_lock_init(&my_cq->task_lock);
+       atomic_set(&my_cq->nr_events, 0);
        init_waitqueue_head(&my_cq->wait_completion);
        my_cq->ownpid = current->tgid;
 
@@ -162,9 +163,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
                        goto create_cq_exit1;
                }
 
-               spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+               write_lock_irqsave(&ehca_cq_idr_lock, flags);
                ret = idr_get_new(&ehca_cq_idr, my_cq, &my_cq->token);
-               spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+               write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
        } while (ret == -EAGAIN);
 
@@ -293,9 +294,9 @@ create_cq_exit3:
                         "cq_num=%x h_ret=%lx", my_cq, my_cq->cq_number, h_ret);
 
 create_cq_exit2:
-       spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+       write_lock_irqsave(&ehca_cq_idr_lock, flags);
        idr_remove(&ehca_cq_idr, my_cq->token);
-       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+       write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
 create_cq_exit1:
        kmem_cache_free(cq_cache, my_cq);
@@ -303,16 +304,6 @@ create_cq_exit1:
        return cq;
 }
 
-static int get_cq_nr_events(struct ehca_cq *my_cq)
-{
-       int ret;
-       unsigned long flags;
-       spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-       ret = my_cq->nr_events;
-       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-       return ret;
-}
-
 int ehca_destroy_cq(struct ib_cq *cq)
 {
        u64 h_ret;
@@ -339,17 +330,18 @@ int ehca_destroy_cq(struct ib_cq *cq)
                }
        }
 
-       spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-       while (my_cq->nr_events) {
-               spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-               wait_event(my_cq->wait_completion, !get_cq_nr_events(my_cq));
-               spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-               /* recheck nr_events to assure no cqe has just arrived */
-       }
-
+       /*
+        * remove the CQ from the idr first to make sure
+        * no more interrupt tasklets will touch this CQ
+        */
+       write_lock_irqsave(&ehca_cq_idr_lock, flags);
        idr_remove(&ehca_cq_idr, my_cq->token);
-       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+       write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+
+       /* now wait until all pending events have completed */
+       wait_event(my_cq->wait_completion, !atomic_read(&my_cq->nr_events));
 
+       /* nobody's using our CQ any longer -- we can destroy it */
        h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0);
        if (h_ret == H_R_STATE) {
                /* cq in err: read err data and destroy it forcibly */
index 32b55a4f0e5bbe604fd607e4fcdaac343f3e5a86..bbd3c6a5822f1d0b65cc97f536e1a3ee7d33719e 100644 (file)
 
 int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
 {
-       int ret = 0;
+       int i, ret = 0;
        struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
                                              ib_device);
        struct hipz_query_hca *rblock;
 
+       static const u32 cap_mapping[] = {
+               IB_DEVICE_RESIZE_MAX_WR,      HCA_CAP_WQE_RESIZE,
+               IB_DEVICE_BAD_PKEY_CNTR,      HCA_CAP_BAD_P_KEY_CTR,
+               IB_DEVICE_BAD_QKEY_CNTR,      HCA_CAP_Q_KEY_VIOL_CTR,
+               IB_DEVICE_RAW_MULTI,          HCA_CAP_RAW_PACKET_MCAST,
+               IB_DEVICE_AUTO_PATH_MIG,      HCA_CAP_AUTO_PATH_MIG,
+               IB_DEVICE_CHANGE_PHY_PORT,    HCA_CAP_SQD_RTS_PORT_CHANGE,
+               IB_DEVICE_UD_AV_PORT_ENFORCE, HCA_CAP_AH_PORT_NR_CHECK,
+               IB_DEVICE_CURR_QP_STATE_MOD,  HCA_CAP_CUR_QP_STATE_MOD,
+               IB_DEVICE_SHUTDOWN_PORT,      HCA_CAP_SHUTDOWN_PORT,
+               IB_DEVICE_INIT_TYPE,          HCA_CAP_INIT_TYPE,
+               IB_DEVICE_PORT_ACTIVE_EVENT,  HCA_CAP_PORT_ACTIVE_EVENT,
+       };
+
        rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
        if (!rblock) {
                ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
@@ -96,6 +110,13 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
        props->max_total_mcast_qp_attach
                = min_t(int, rblock->max_total_mcast_qp_attach, INT_MAX);
 
+       /* translate device capabilities */
+       props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID |
+               IB_DEVICE_RC_RNR_NAK_GEN | IB_DEVICE_N_NOTIFY_CQ;
+       for (i = 0; i < ARRAY_SIZE(cap_mapping); i += 2)
+               if (rblock->hca_cap_indicators & cap_mapping[i + 1])
+                       props->device_cap_flags |= cap_mapping[i];
+
 query_device1:
        ehca_free_fw_ctrlblock(rblock);
 
@@ -172,6 +193,40 @@ query_port1:
        return ret;
 }
 
+int ehca_query_sma_attr(struct ehca_shca *shca,
+                       u8 port, struct ehca_sma_attr *attr)
+{
+       int ret = 0;
+       struct hipz_query_port *rblock;
+
+       rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
+       if (!rblock) {
+               ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
+               return -ENOMEM;
+       }
+
+       if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "Can't query port properties");
+               ret = -EINVAL;
+               goto query_sma_attr1;
+       }
+
+       memset(attr, 0, sizeof(struct ehca_sma_attr));
+
+       attr->lid    = rblock->lid;
+       attr->lmc    = rblock->lmc;
+       attr->sm_sl  = rblock->sm_sl;
+       attr->sm_lid = rblock->sm_lid;
+
+       attr->pkey_tbl_len = rblock->pkey_tbl_len;
+       memcpy(attr->pkeys, rblock->pkey_entries, sizeof(attr->pkeys));
+
+query_sma_attr1:
+       ehca_free_fw_ctrlblock(rblock);
+
+       return ret;
+}
+
 int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
 {
        int ret = 0;
@@ -261,7 +316,7 @@ int ehca_modify_port(struct ib_device *ibdev,
        }
 
        if (mutex_lock_interruptible(&shca->modify_mutex))
-                return -ERESTARTSYS;
+               return -ERESTARTSYS;
 
        rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
        if (!rblock) {
@@ -290,7 +345,7 @@ modify_port2:
        ehca_free_fw_ctrlblock(rblock);
 
 modify_port1:
-        mutex_unlock(&shca->modify_mutex);
+       mutex_unlock(&shca->modify_mutex);
 
        return ret;
 }
index 100329ba33439f79c30c391e17c9e677dbe8c979..96eba383075437e4dfea5deb10e307b693282ed4 100644 (file)
@@ -5,6 +5,8 @@
  *
  *  Authors: Heiko J Schick <schickhj@de.ibm.com>
  *           Khadija Souissi <souissi@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
  *
  *  Copyright (c) 2005 IBM Corporation
  *
@@ -59,6 +61,7 @@
 #define NEQE_EVENT_CODE        EHCA_BMASK_IBM(2,7)
 #define NEQE_PORT_NUMBER       EHCA_BMASK_IBM(8,15)
 #define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16,16)
+#define NEQE_DISRUPTIVE        EHCA_BMASK_IBM(16,16)
 
 #define ERROR_DATA_LENGTH      EHCA_BMASK_IBM(52,63)
 #define ERROR_DATA_TYPE        EHCA_BMASK_IBM(0,7)
@@ -178,12 +181,11 @@ static void qp_event_callback(struct ehca_shca *shca,
 {
        struct ib_event event;
        struct ehca_qp *qp;
-       unsigned long flags;
        u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe);
 
-       spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+       read_lock(&ehca_qp_idr_lock);
        qp = idr_find(&ehca_qp_idr, token);
-       spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+       read_unlock(&ehca_qp_idr_lock);
 
 
        if (!qp)
@@ -207,18 +209,22 @@ static void cq_event_callback(struct ehca_shca *shca,
                              u64 eqe)
 {
        struct ehca_cq *cq;
-       unsigned long flags;
        u32 token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe);
 
-       spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+       read_lock(&ehca_cq_idr_lock);
        cq = idr_find(&ehca_cq_idr, token);
-       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+       if (cq)
+               atomic_inc(&cq->nr_events);
+       read_unlock(&ehca_cq_idr_lock);
 
        if (!cq)
                return;
 
        ehca_error_data(shca, cq, cq->ipz_cq_handle.handle);
 
+       if (atomic_dec_and_test(&cq->nr_events))
+               wake_up(&cq->wait_completion);
+
        return;
 }
 
@@ -281,30 +287,61 @@ static void parse_identifier(struct ehca_shca *shca, u64 eqe)
        return;
 }
 
-static void parse_ec(struct ehca_shca *shca, u64 eqe)
+static void dispatch_port_event(struct ehca_shca *shca, int port_num,
+                               enum ib_event_type type, const char *msg)
 {
        struct ib_event event;
+
+       ehca_info(&shca->ib_device, "port %d %s.", port_num, msg);
+       event.device = &shca->ib_device;
+       event.event = type;
+       event.element.port_num = port_num;
+       ib_dispatch_event(&event);
+}
+
+static void notify_port_conf_change(struct ehca_shca *shca, int port_num)
+{
+       struct ehca_sma_attr  new_attr;
+       struct ehca_sma_attr *old_attr = &shca->sport[port_num - 1].saved_attr;
+
+       ehca_query_sma_attr(shca, port_num, &new_attr);
+
+       if (new_attr.sm_sl  != old_attr->sm_sl ||
+           new_attr.sm_lid != old_attr->sm_lid)
+               dispatch_port_event(shca, port_num, IB_EVENT_SM_CHANGE,
+                                   "SM changed");
+
+       if (new_attr.lid != old_attr->lid ||
+           new_attr.lmc != old_attr->lmc)
+               dispatch_port_event(shca, port_num, IB_EVENT_LID_CHANGE,
+                                   "LID changed");
+
+       if (new_attr.pkey_tbl_len != old_attr->pkey_tbl_len ||
+           memcmp(new_attr.pkeys, old_attr->pkeys,
+                  sizeof(u16) * new_attr.pkey_tbl_len))
+               dispatch_port_event(shca, port_num, IB_EVENT_PKEY_CHANGE,
+                                   "P_Key changed");
+
+       *old_attr = new_attr;
+}
+
+static void parse_ec(struct ehca_shca *shca, u64 eqe)
+{
        u8 ec   = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
        u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
 
        switch (ec) {
        case 0x30: /* port availability change */
                if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
-                       ehca_info(&shca->ib_device,
-                                 "port %x is active.", port);
-                       event.device = &shca->ib_device;
-                       event.event = IB_EVENT_PORT_ACTIVE;
-                       event.element.port_num = port;
                        shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
-                       ib_dispatch_event(&event);
+                       dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+                                           "is active");
+                       ehca_query_sma_attr(shca, port,
+                                           &shca->sport[port - 1].saved_attr);
                } else {
-                       ehca_info(&shca->ib_device,
-                                 "port %x is inactive.", port);
-                       event.device = &shca->ib_device;
-                       event.event = IB_EVENT_PORT_ERR;
-                       event.element.port_num = port;
                        shca->sport[port - 1].port_state = IB_PORT_DOWN;
-                       ib_dispatch_event(&event);
+                       dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+                                           "is inactive");
                }
                break;
        case 0x31:
@@ -312,24 +349,19 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
                 * disruptive change is caused by
                 * LID, PKEY or SM change
                 */
-               ehca_warn(&shca->ib_device,
-                         "disruptive port %x configuration change", port);
-
-               ehca_info(&shca->ib_device,
-                         "port %x is inactive.", port);
-               event.device = &shca->ib_device;
-               event.event = IB_EVENT_PORT_ERR;
-               event.element.port_num = port;
-               shca->sport[port - 1].port_state = IB_PORT_DOWN;
-               ib_dispatch_event(&event);
-
-               ehca_info(&shca->ib_device,
-                         "port %x is active.", port);
-               event.device = &shca->ib_device;
-               event.event = IB_EVENT_PORT_ACTIVE;
-               event.element.port_num = port;
-               shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
-               ib_dispatch_event(&event);
+               if (EHCA_BMASK_GET(NEQE_DISRUPTIVE, eqe)) {
+                       ehca_warn(&shca->ib_device, "disruptive port "
+                                 "%d configuration change", port);
+
+                       shca->sport[port - 1].port_state = IB_PORT_DOWN;
+                       dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+                                           "is inactive");
+
+                       shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
+                       dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+                                           "is active");
+               } else
+                       notify_port_conf_change(shca, port);
                break;
        case 0x32: /* adapter malfunction */
                ehca_err(&shca->ib_device, "Adapter malfunction.");
@@ -404,7 +436,6 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
 {
        u64 eqe_value;
        u32 token;
-       unsigned long flags;
        struct ehca_cq *cq;
 
        eqe_value = eqe->entry;
@@ -412,27 +443,24 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
        if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
                ehca_dbg(&shca->ib_device, "Got completion event");
                token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
-               spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+               read_lock(&ehca_cq_idr_lock);
                cq = idr_find(&ehca_cq_idr, token);
+               if (cq)
+                       atomic_inc(&cq->nr_events);
+               read_unlock(&ehca_cq_idr_lock);
                if (cq == NULL) {
-                       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
                        ehca_err(&shca->ib_device,
                                 "Invalid eqe for non-existing cq token=%x",
                                 token);
                        return;
                }
                reset_eq_pending(cq);
-               cq->nr_events++;
-               spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
                if (ehca_scaling_code)
                        queue_comp_task(cq);
                else {
                        comp_event_callback(cq);
-                       spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-                       cq->nr_events--;
-                       if (!cq->nr_events)
+                       if (atomic_dec_and_test(&cq->nr_events))
                                wake_up(&cq->wait_completion);
-                       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
                }
        } else {
                ehca_dbg(&shca->ib_device, "Got non completion event");
@@ -476,17 +504,17 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
                eqe_value = eqe_cache[eqe_cnt].eqe->entry;
                if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
                        token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
-                       spin_lock(&ehca_cq_idr_lock);
+                       read_lock(&ehca_cq_idr_lock);
                        eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token);
+                       if (eqe_cache[eqe_cnt].cq)
+                               atomic_inc(&eqe_cache[eqe_cnt].cq->nr_events);
+                       read_unlock(&ehca_cq_idr_lock);
                        if (!eqe_cache[eqe_cnt].cq) {
-                               spin_unlock(&ehca_cq_idr_lock);
                                ehca_err(&shca->ib_device,
                                         "Invalid eqe for non-existing cq "
                                         "token=%x", token);
                                continue;
                        }
-                       eqe_cache[eqe_cnt].cq->nr_events++;
-                       spin_unlock(&ehca_cq_idr_lock);
                } else
                        eqe_cache[eqe_cnt].cq = NULL;
                eqe_cnt++;
@@ -517,11 +545,8 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
                        else {
                                struct ehca_cq *cq = eq->eqe_cache[i].cq;
                                comp_event_callback(cq);
-                               spin_lock(&ehca_cq_idr_lock);
-                               cq->nr_events--;
-                               if (!cq->nr_events)
+                               if (atomic_dec_and_test(&cq->nr_events))
                                        wake_up(&cq->wait_completion);
-                               spin_unlock(&ehca_cq_idr_lock);
                        }
                } else {
                        ehca_dbg(&shca->ib_device, "Got non completion event");
@@ -621,13 +646,10 @@ static void run_comp_task(struct ehca_cpu_comp_task* cct)
        while (!list_empty(&cct->cq_list)) {
                cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
                spin_unlock_irqrestore(&cct->task_lock, flags);
-               comp_event_callback(cq);
 
-               spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-               cq->nr_events--;
-               if (!cq->nr_events)
+               comp_event_callback(cq);
+               if (atomic_dec_and_test(&cq->nr_events))
                        wake_up(&cq->wait_completion);
-               spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
                spin_lock_irqsave(&cct->task_lock, flags);
                spin_lock(&cq->task_lock);
index 6ed06ee033ed2f326a6674d21701eed3479fa2df..3346cb06cea62a4d4a4036364fba3cf174756dda 100644 (file)
@@ -47,7 +47,6 @@ struct ehca_shca;
 
 #include <linux/interrupt.h>
 #include <linux/types.h>
-#include <asm/atomic.h>
 
 int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource);
 
index 37e7fe0908cfad268e8da90142f9d6f8aeaa85ec..77aeca6a2c2f3e2428dd989b8eabc4afa496fd5d 100644 (file)
@@ -49,6 +49,9 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props);
 int ehca_query_port(struct ib_device *ibdev, u8 port,
                    struct ib_port_attr *props);
 
+int ehca_query_sma_attr(struct ehca_shca *shca, u8 port,
+                       struct ehca_sma_attr *attr);
+
 int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey);
 
 int ehca_query_gid(struct ib_device *ibdev, u8 port, int index,
@@ -154,6 +157,21 @@ int ehca_post_send(struct ib_qp *qp, struct ib_send_wr *send_wr,
 int ehca_post_recv(struct ib_qp *qp, struct ib_recv_wr *recv_wr,
                   struct ib_recv_wr **bad_recv_wr);
 
+int ehca_post_srq_recv(struct ib_srq *srq,
+                      struct ib_recv_wr *recv_wr,
+                      struct ib_recv_wr **bad_recv_wr);
+
+struct ib_srq *ehca_create_srq(struct ib_pd *pd,
+                              struct ib_srq_init_attr *init_attr,
+                              struct ib_udata *udata);
+
+int ehca_modify_srq(struct ib_srq *srq, struct ib_srq_attr *attr,
+                   enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
+
+int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
+
+int ehca_destroy_srq(struct ib_srq *srq);
+
 u64 ehca_define_sqp(struct ehca_shca *shca, struct ehca_qp *ibqp,
                    struct ib_qp_init_attr *qp_init_attr);
 
index c3f99f33b49c59bfa5d357dc0771eb0c787e9831..28ba2dd242165f626ead5afc46f43a978de18d9b 100644 (file)
@@ -94,17 +94,15 @@ MODULE_PARM_DESC(poll_all_eqs,
 MODULE_PARM_DESC(static_rate,
                 "set permanent static rate (default: disabled)");
 MODULE_PARM_DESC(scaling_code,
-                "set scaling code (0: disabled, 1: enabled/default)");
+                "set scaling code (0: disabled/default, 1: enabled)");
 
-spinlock_t ehca_qp_idr_lock;
-spinlock_t ehca_cq_idr_lock;
-spinlock_t hcall_lock;
+DEFINE_RWLOCK(ehca_qp_idr_lock);
+DEFINE_RWLOCK(ehca_cq_idr_lock);
 DEFINE_IDR(ehca_qp_idr);
 DEFINE_IDR(ehca_cq_idr);
 
-
-static struct list_head shca_list; /* list of all registered ehcas */
-static spinlock_t shca_list_lock;
+static LIST_HEAD(shca_list); /* list of all registered ehcas */
+static DEFINE_SPINLOCK(shca_list_lock);
 
 static struct timer_list poll_eqs_timer;
 
@@ -205,11 +203,35 @@ static void ehca_destroy_slab_caches(void)
 #define EHCA_HCAAVER  EHCA_BMASK_IBM(32,39)
 #define EHCA_REVID    EHCA_BMASK_IBM(40,63)
 
+static struct cap_descr {
+       u64 mask;
+       char *descr;
+} hca_cap_descr[] = {
+       { HCA_CAP_AH_PORT_NR_CHECK, "HCA_CAP_AH_PORT_NR_CHECK" },
+       { HCA_CAP_ATOMIC, "HCA_CAP_ATOMIC" },
+       { HCA_CAP_AUTO_PATH_MIG, "HCA_CAP_AUTO_PATH_MIG" },
+       { HCA_CAP_BAD_P_KEY_CTR, "HCA_CAP_BAD_P_KEY_CTR" },
+       { HCA_CAP_SQD_RTS_PORT_CHANGE, "HCA_CAP_SQD_RTS_PORT_CHANGE" },
+       { HCA_CAP_CUR_QP_STATE_MOD, "HCA_CAP_CUR_QP_STATE_MOD" },
+       { HCA_CAP_INIT_TYPE, "HCA_CAP_INIT_TYPE" },
+       { HCA_CAP_PORT_ACTIVE_EVENT, "HCA_CAP_PORT_ACTIVE_EVENT" },
+       { HCA_CAP_Q_KEY_VIOL_CTR, "HCA_CAP_Q_KEY_VIOL_CTR" },
+       { HCA_CAP_WQE_RESIZE, "HCA_CAP_WQE_RESIZE" },
+       { HCA_CAP_RAW_PACKET_MCAST, "HCA_CAP_RAW_PACKET_MCAST" },
+       { HCA_CAP_SHUTDOWN_PORT, "HCA_CAP_SHUTDOWN_PORT" },
+       { HCA_CAP_RC_LL_QP, "HCA_CAP_RC_LL_QP" },
+       { HCA_CAP_SRQ, "HCA_CAP_SRQ" },
+       { HCA_CAP_UD_LL_QP, "HCA_CAP_UD_LL_QP" },
+       { HCA_CAP_RESIZE_MR, "HCA_CAP_RESIZE_MR" },
+       { HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" },
+};
+
 int ehca_sense_attributes(struct ehca_shca *shca)
 {
-       int ret = 0;
+       int i, ret = 0;
        u64 h_ret;
        struct hipz_query_hca *rblock;
+       struct hipz_query_port *port;
 
        rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
        if (!rblock) {
@@ -222,7 +244,7 @@ int ehca_sense_attributes(struct ehca_shca *shca)
                ehca_gen_err("Cannot query device properties. h_ret=%lx",
                             h_ret);
                ret = -EPERM;
-               goto num_ports1;
+               goto sense_attributes1;
        }
 
        if (ehca_nr_ports == 1)
@@ -242,18 +264,44 @@ int ehca_sense_attributes(struct ehca_shca *shca)
                ehca_gen_dbg(" ... hardware version=%x:%x", hcaaver, revid);
 
                if ((hcaaver == 1) && (revid == 0))
-                       shca->hw_level = 0;
+                       shca->hw_level = 0x11;
                else if ((hcaaver == 1) && (revid == 1))
-                       shca->hw_level = 1;
+                       shca->hw_level = 0x12;
                else if ((hcaaver == 1) && (revid == 2))
-                       shca->hw_level = 2;
+                       shca->hw_level = 0x13;
+               else if ((hcaaver == 2) && (revid == 0))
+                       shca->hw_level = 0x21;
+               else if ((hcaaver == 2) && (revid == 0x10))
+                       shca->hw_level = 0x22;
+               else {
+                       ehca_gen_warn("unknown hardware version"
+                                     " - assuming default level");
+                       shca->hw_level = 0x22;
+               }
        }
        ehca_gen_dbg(" ... hardware level=%x", shca->hw_level);
 
        shca->sport[0].rate = IB_RATE_30_GBPS;
        shca->sport[1].rate = IB_RATE_30_GBPS;
 
-num_ports1:
+       shca->hca_cap = rblock->hca_cap_indicators;
+       ehca_gen_dbg(" ... HCA capabilities:");
+       for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++)
+               if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap))
+                       ehca_gen_dbg("   %s", hca_cap_descr[i].descr);
+
+       port = (struct hipz_query_port *) rblock;
+       h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
+       if (h_ret != H_SUCCESS) {
+               ehca_gen_err("Cannot query port properties. h_ret=%lx",
+                            h_ret);
+               ret = -EPERM;
+               goto sense_attributes1;
+       }
+
+       shca->max_mtu = port->max_mtu;
+
+sense_attributes1:
        ehca_free_fw_ctrlblock(rblock);
        return ret;
 }
@@ -293,7 +341,7 @@ int ehca_init_device(struct ehca_shca *shca)
        strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX);
        shca->ib_device.owner               = THIS_MODULE;
 
-       shca->ib_device.uverbs_abi_ver      = 6;
+       shca->ib_device.uverbs_abi_ver      = 7;
        shca->ib_device.uverbs_cmd_mask     =
                (1ull << IB_USER_VERBS_CMD_GET_CONTEXT)         |
                (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)        |
@@ -361,6 +409,20 @@ int ehca_init_device(struct ehca_shca *shca)
        /* shca->ib_device.process_mad      = ehca_process_mad;     */
        shca->ib_device.mmap                = ehca_mmap;
 
+       if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
+               shca->ib_device.uverbs_cmd_mask |=
+                       (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
+                       (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
+                       (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
+                       (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+
+               shca->ib_device.create_srq          = ehca_create_srq;
+               shca->ib_device.modify_srq          = ehca_modify_srq;
+               shca->ib_device.query_srq           = ehca_query_srq;
+               shca->ib_device.destroy_srq         = ehca_destroy_srq;
+               shca->ib_device.post_srq_recv       = ehca_post_srq_recv;
+       }
+
        return ret;
 }
 
@@ -800,14 +862,6 @@ int __init ehca_module_init(void)
 
        printk(KERN_INFO "eHCA Infiniband Device Driver "
               "(Rel.: SVNEHCA_0023)\n");
-       idr_init(&ehca_qp_idr);
-       idr_init(&ehca_cq_idr);
-       spin_lock_init(&ehca_qp_idr_lock);
-       spin_lock_init(&ehca_cq_idr_lock);
-       spin_lock_init(&hcall_lock);
-
-       INIT_LIST_HEAD(&shca_list);
-       spin_lock_init(&shca_list_lock);
 
        if ((ret = ehca_create_comp_pool())) {
                ehca_gen_err("Cannot create comp pool.");
index b5bc787c77b655fda3404b2a08f273590921f951..74671250303f00433247cae49679b89be401a6f8 100644 (file)
@@ -3,7 +3,9 @@
  *
  *  QP functions
  *
- *  Authors: Waleri Fomin <fomin@de.ibm.com>
+ *  Authors: Joachim Fenkes <fenkes@de.ibm.com>
+ *           Stefan Roscher <stefan.roscher@de.ibm.com>
+ *           Waleri Fomin <fomin@de.ibm.com>
  *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
  *           Reinhard Ernst <rernst@de.ibm.com>
  *           Heiko J Schick <schickhj@de.ibm.com>
@@ -234,13 +236,6 @@ static inline enum ib_qp_statetrans get_modqp_statetrans(int ib_fromstate,
        return index;
 }
 
-enum ehca_service_type {
-       ST_RC = 0,
-       ST_UC = 1,
-       ST_RD = 2,
-       ST_UD = 3
-};
-
 /*
  * ibqptype2servicetype returns hcp service type corresponding to given
  * ib qp type used by create_qp()
@@ -268,15 +263,34 @@ static inline int ibqptype2servicetype(enum ib_qp_type ibqptype)
 }
 
 /*
- * init_qp_queues initializes/constructs r/squeue and registers queue pages.
+ * init userspace queue info from ipz_queue data
  */
-static inline int init_qp_queues(struct ehca_shca *shca,
-                                struct ehca_qp *my_qp,
-                                int nr_sq_pages,
-                                int nr_rq_pages,
-                                int swqe_size,
-                                int rwqe_size,
-                                int nr_send_sges, int nr_receive_sges)
+static inline void queue2resp(struct ipzu_queue_resp *resp,
+                             struct ipz_queue *queue)
+{
+       resp->qe_size = queue->qe_size;
+       resp->act_nr_of_sg = queue->act_nr_of_sg;
+       resp->queue_length = queue->queue_length;
+       resp->pagesize = queue->pagesize;
+       resp->toggle_state = queue->toggle_state;
+}
+
+static inline int ll_qp_msg_size(int nr_sge)
+{
+       return 128 << nr_sge;
+}
+
+/*
+ * init_qp_queue initializes/constructs r/squeue and registers queue pages.
+ */
+static inline int init_qp_queue(struct ehca_shca *shca,
+                               struct ehca_qp *my_qp,
+                               struct ipz_queue *queue,
+                               int q_type,
+                               u64 expected_hret,
+                               int nr_q_pages,
+                               int wqe_size,
+                               int nr_sges)
 {
        int ret, cnt, ipz_rc;
        void *vpage;
@@ -284,127 +298,93 @@ static inline int init_qp_queues(struct ehca_shca *shca,
        struct ib_device *ib_dev = &shca->ib_device;
        struct ipz_adapter_handle ipz_hca_handle = shca->ipz_hca_handle;
 
-       ipz_rc = ipz_queue_ctor(&my_qp->ipz_squeue,
-                               nr_sq_pages,
-                               EHCA_PAGESIZE, swqe_size, nr_send_sges);
+       if (!nr_q_pages)
+               return 0;
+
+       ipz_rc = ipz_queue_ctor(queue, nr_q_pages, EHCA_PAGESIZE,
+                               wqe_size, nr_sges);
        if (!ipz_rc) {
-               ehca_err(ib_dev,"Cannot allocate page for squeue. ipz_rc=%x",
+               ehca_err(ib_dev, "Cannot allocate page for queue. ipz_rc=%x",
                         ipz_rc);
                return -EBUSY;
        }
 
-       ipz_rc = ipz_queue_ctor(&my_qp->ipz_rqueue,
-                               nr_rq_pages,
-                               EHCA_PAGESIZE, rwqe_size, nr_receive_sges);
-       if (!ipz_rc) {
-               ehca_err(ib_dev, "Cannot allocate page for rqueue. ipz_rc=%x",
-                        ipz_rc);
-               ret = -EBUSY;
-               goto init_qp_queues0;
-       }
-       /* register SQ pages */
-       for (cnt = 0; cnt < nr_sq_pages; cnt++) {
-               vpage = ipz_qpageit_get_inc(&my_qp->ipz_squeue);
+       /* register queue pages */
+       for (cnt = 0; cnt < nr_q_pages; cnt++) {
+               vpage = ipz_qpageit_get_inc(queue);
                if (!vpage) {
-                       ehca_err(ib_dev, "SQ ipz_qpageit_get_inc() "
+                       ehca_err(ib_dev, "ipz_qpageit_get_inc() "
                                 "failed p_vpage= %p", vpage);
                        ret = -EINVAL;
-                       goto init_qp_queues1;
+                       goto init_qp_queue1;
                }
                rpage = virt_to_abs(vpage);
 
                h_ret = hipz_h_register_rpage_qp(ipz_hca_handle,
                                                 my_qp->ipz_qp_handle,
-                                                &my_qp->pf, 0, 0,
+                                                NULL, 0, q_type,
                                                 rpage, 1,
                                                 my_qp->galpas.kernel);
-               if (h_ret < H_SUCCESS) {
-                       ehca_err(ib_dev, "SQ hipz_qp_register_rpage()"
-                                " failed rc=%lx", h_ret);
-                       ret = ehca2ib_return_code(h_ret);
-                       goto init_qp_queues1;
-               }
-       }
-
-       ipz_qeit_reset(&my_qp->ipz_squeue);
-
-       /* register RQ pages */
-       for (cnt = 0; cnt < nr_rq_pages; cnt++) {
-               vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue);
-               if (!vpage) {
-                       ehca_err(ib_dev, "RQ ipz_qpageit_get_inc() "
-                                "failed p_vpage = %p", vpage);
-                       ret = -EINVAL;
-                       goto init_qp_queues1;
-               }
-
-               rpage = virt_to_abs(vpage);
-
-               h_ret = hipz_h_register_rpage_qp(ipz_hca_handle,
-                                                my_qp->ipz_qp_handle,
-                                                &my_qp->pf, 0, 1,
-                                                rpage, 1,my_qp->galpas.kernel);
-               if (h_ret < H_SUCCESS) {
-                       ehca_err(ib_dev, "RQ hipz_qp_register_rpage() failed "
-                                "rc=%lx", h_ret);
-                       ret = ehca2ib_return_code(h_ret);
-                       goto init_qp_queues1;
-               }
-               if (cnt == (nr_rq_pages - 1)) { /* last page! */
-                       if (h_ret != H_SUCCESS) {
-                               ehca_err(ib_dev, "RQ hipz_qp_register_rpage() "
+               if (cnt == (nr_q_pages - 1)) {  /* last page! */
+                       if (h_ret != expected_hret) {
+                               ehca_err(ib_dev, "hipz_qp_register_rpage() "
                                         "h_ret= %lx ", h_ret);
                                ret = ehca2ib_return_code(h_ret);
-                               goto init_qp_queues1;
+                               goto init_qp_queue1;
                        }
                        vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue);
                        if (vpage) {
                                ehca_err(ib_dev, "ipz_qpageit_get_inc() "
                                         "should not succeed vpage=%p", vpage);
                                ret = -EINVAL;
-                               goto init_qp_queues1;
+                               goto init_qp_queue1;
                        }
                } else {
                        if (h_ret != H_PAGE_REGISTERED) {
-                               ehca_err(ib_dev, "RQ hipz_qp_register_rpage() "
+                               ehca_err(ib_dev, "hipz_qp_register_rpage() "
                                         "h_ret= %lx ", h_ret);
                                ret = ehca2ib_return_code(h_ret);
-                               goto init_qp_queues1;
+                               goto init_qp_queue1;
                        }
                }
        }
 
-       ipz_qeit_reset(&my_qp->ipz_rqueue);
+       ipz_qeit_reset(queue);
 
        return 0;
 
-init_qp_queues1:
-       ipz_queue_dtor(&my_qp->ipz_rqueue);
-init_qp_queues0:
-       ipz_queue_dtor(&my_qp->ipz_squeue);
+init_qp_queue1:
+       ipz_queue_dtor(queue);
        return ret;
 }
 
-struct ib_qp *ehca_create_qp(struct ib_pd *pd,
-                            struct ib_qp_init_attr *init_attr,
-                            struct ib_udata *udata)
+/*
+ * Create an ib_qp struct that is either a QP or an SRQ, depending on
+ * the value of the is_srq parameter. If init_attr and srq_init_attr share
+ * fields, the field out of init_attr is used.
+ */
+struct ehca_qp *internal_create_qp(struct ib_pd *pd,
+                                  struct ib_qp_init_attr *init_attr,
+                                  struct ib_srq_init_attr *srq_init_attr,
+                                  struct ib_udata *udata, int is_srq)
 {
-       static int da_rc_msg_size[]={ 128, 256, 512, 1024, 2048, 4096 };
-       static int da_ud_sq_msg_size[]={ 128, 384, 896, 1920, 3968 };
        struct ehca_qp *my_qp;
        struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
        struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
                                              ib_device);
        struct ib_ucontext *context = NULL;
        u64 h_ret;
-       int max_send_sge, max_recv_sge, ret;
+       int is_llqp = 0, has_srq = 0;
+       int qp_type, max_send_sge, max_recv_sge, ret;
 
        /* h_call's out parameters */
        struct ehca_alloc_qp_parms parms;
-       u32 swqe_size = 0, rwqe_size = 0;
-       u8 daqp_completion, isdaqp;
+       u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
        unsigned long flags;
 
+       memset(&parms, 0, sizeof(parms));
+       qp_type = init_attr->qp_type;
+
        if (init_attr->sq_sig_type != IB_SIGNAL_REQ_WR &&
                init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) {
                ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed",
@@ -412,41 +392,98 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
                return ERR_PTR(-EINVAL);
        }
 
-       /* save daqp completion bits */
-       daqp_completion = init_attr->qp_type & 0x60;
-       /* save daqp bit */
-       isdaqp = (init_attr->qp_type & 0x80) ? 1 : 0;
-       init_attr->qp_type = init_attr->qp_type & 0x1F;
+       /* save LLQP info */
+       if (qp_type & 0x80) {
+               is_llqp = 1;
+               parms.ext_type = EQPT_LLQP;
+               parms.ll_comp_flags = qp_type & LLQP_COMP_MASK;
+       }
+       qp_type &= 0x1F;
+       init_attr->qp_type &= 0x1F;
 
-       if (init_attr->qp_type != IB_QPT_UD &&
-           init_attr->qp_type != IB_QPT_SMI &&
-           init_attr->qp_type != IB_QPT_GSI &&
-           init_attr->qp_type != IB_QPT_UC &&
-           init_attr->qp_type != IB_QPT_RC) {
-               ehca_err(pd->device, "wrong QP Type=%x", init_attr->qp_type);
-               return ERR_PTR(-EINVAL);
+       /* handle SRQ base QPs */
+       if (init_attr->srq) {
+               struct ehca_qp *my_srq =
+                       container_of(init_attr->srq, struct ehca_qp, ib_srq);
+
+               has_srq = 1;
+               parms.ext_type = EQPT_SRQBASE;
+               parms.srq_qpn = my_srq->real_qp_num;
+               parms.srq_token = my_srq->token;
        }
-       if ((init_attr->qp_type != IB_QPT_RC && init_attr->qp_type != IB_QPT_UD)
-           && isdaqp) {
-               ehca_err(pd->device, "unsupported LL QP Type=%x",
-                        init_attr->qp_type);
+
+       if (is_llqp && has_srq) {
+               ehca_err(pd->device, "LLQPs can't have an SRQ");
                return ERR_PTR(-EINVAL);
-       } else if (init_attr->qp_type == IB_QPT_RC && isdaqp &&
-                  (init_attr->cap.max_send_wr > 255 ||
-                   init_attr->cap.max_recv_wr > 255 )) {
-                      ehca_err(pd->device, "Invalid Number of max_sq_wr =%x "
-                               "or max_rq_wr=%x for QP Type=%x",
-                               init_attr->cap.max_send_wr,
-                               init_attr->cap.max_recv_wr,init_attr->qp_type);
-                      return ERR_PTR(-EINVAL);
-       } else if (init_attr->qp_type == IB_QPT_UD && isdaqp &&
-                 init_attr->cap.max_send_wr > 255) {
-               ehca_err(pd->device,
-                        "Invalid Number of max_send_wr=%x for UD QP_TYPE=%x",
-                        init_attr->cap.max_send_wr, init_attr->qp_type);
+       }
+
+       /* handle SRQs */
+       if (is_srq) {
+               parms.ext_type = EQPT_SRQ;
+               parms.srq_limit = srq_init_attr->attr.srq_limit;
+               if (init_attr->cap.max_recv_sge > 3) {
+                       ehca_err(pd->device, "no more than three SGEs "
+                                "supported for SRQ  pd=%p  max_sge=%x",
+                                pd, init_attr->cap.max_recv_sge);
+                       return ERR_PTR(-EINVAL);
+               }
+       }
+
+       /* check QP type */
+       if (qp_type != IB_QPT_UD &&
+           qp_type != IB_QPT_UC &&
+           qp_type != IB_QPT_RC &&
+           qp_type != IB_QPT_SMI &&
+           qp_type != IB_QPT_GSI) {
+               ehca_err(pd->device, "wrong QP Type=%x", qp_type);
                return ERR_PTR(-EINVAL);
        }
 
+       if (is_llqp) {
+               switch (qp_type) {
+               case IB_QPT_RC:
+                       if ((init_attr->cap.max_send_wr > 255) ||
+                           (init_attr->cap.max_recv_wr > 255)) {
+                               ehca_err(pd->device,
+                                        "Invalid Number of max_sq_wr=%x "
+                                        "or max_rq_wr=%x for RC LLQP",
+                                        init_attr->cap.max_send_wr,
+                                        init_attr->cap.max_recv_wr);
+                               return ERR_PTR(-EINVAL);
+                       }
+                       break;
+               case IB_QPT_UD:
+                       if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) {
+                               ehca_err(pd->device, "UD LLQP not supported "
+                                        "by this adapter");
+                               return ERR_PTR(-ENOSYS);
+                       }
+                       if (!(init_attr->cap.max_send_sge <= 5
+                           && init_attr->cap.max_send_sge >= 1
+                           && init_attr->cap.max_recv_sge <= 5
+                           && init_attr->cap.max_recv_sge >= 1)) {
+                               ehca_err(pd->device,
+                                        "Invalid Number of max_send_sge=%x "
+                                        "or max_recv_sge=%x for UD LLQP",
+                                        init_attr->cap.max_send_sge,
+                                        init_attr->cap.max_recv_sge);
+                               return ERR_PTR(-EINVAL);
+                       } else if (init_attr->cap.max_send_wr > 255) {
+                               ehca_err(pd->device,
+                                        "Invalid Number of "
+                                        "ax_send_wr=%x for UD QP_TYPE=%x",
+                                        init_attr->cap.max_send_wr, qp_type);
+                               return ERR_PTR(-EINVAL);
+                       }
+                       break;
+               default:
+                       ehca_err(pd->device, "unsupported LL QP Type=%x",
+                                qp_type);
+                       return ERR_PTR(-EINVAL);
+                       break;
+               }
+       }
+
        if (pd->uobject && udata)
                context = pd->uobject->context;
 
@@ -456,16 +493,17 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
                return ERR_PTR(-ENOMEM);
        }
 
-       memset (&parms, 0, sizeof(struct ehca_alloc_qp_parms));
        spin_lock_init(&my_qp->spinlock_s);
        spin_lock_init(&my_qp->spinlock_r);
+       my_qp->qp_type = qp_type;
+       my_qp->ext_type = parms.ext_type;
 
-       my_qp->recv_cq =
-               container_of(init_attr->recv_cq, struct ehca_cq, ib_cq);
-       my_qp->send_cq =
-               container_of(init_attr->send_cq, struct ehca_cq, ib_cq);
-
-       my_qp->init_attr = *init_attr;
+       if (init_attr->recv_cq)
+               my_qp->recv_cq =
+                       container_of(init_attr->recv_cq, struct ehca_cq, ib_cq);
+       if (init_attr->send_cq)
+               my_qp->send_cq =
+                       container_of(init_attr->send_cq, struct ehca_cq, ib_cq);
 
        do {
                if (!idr_pre_get(&ehca_qp_idr, GFP_KERNEL)) {
@@ -474,9 +512,9 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
                        goto create_qp_exit0;
                }
 
-               spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+               write_lock_irqsave(&ehca_qp_idr_lock, flags);
                ret = idr_get_new(&ehca_qp_idr, my_qp, &my_qp->token);
-               spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+               write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
 
        } while (ret == -EAGAIN);
 
@@ -486,10 +524,10 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
                goto create_qp_exit0;
        }
 
-       parms.servicetype = ibqptype2servicetype(init_attr->qp_type);
+       parms.servicetype = ibqptype2servicetype(qp_type);
        if (parms.servicetype < 0) {
                ret = -EINVAL;
-               ehca_err(pd->device, "Invalid qp_type=%x", init_attr->qp_type);
+               ehca_err(pd->device, "Invalid qp_type=%x", qp_type);
                goto create_qp_exit0;
        }
 
@@ -501,21 +539,25 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
        /* UD_AV CIRCUMVENTION */
        max_send_sge = init_attr->cap.max_send_sge;
        max_recv_sge = init_attr->cap.max_recv_sge;
-       if (IB_QPT_UD == init_attr->qp_type ||
-           IB_QPT_GSI == init_attr->qp_type ||
-           IB_QPT_SMI == init_attr->qp_type) {
+       if (parms.servicetype == ST_UD && !is_llqp) {
                max_send_sge += 2;
                max_recv_sge += 2;
        }
 
-       parms.ipz_eq_handle = shca->eq.ipz_eq_handle;
-       parms.daqp_ctrl = isdaqp | daqp_completion;
+       parms.token = my_qp->token;
+       parms.eq_handle = shca->eq.ipz_eq_handle;
        parms.pd = my_pd->fw_pd;
-       parms.max_recv_sge = max_recv_sge;
-       parms.max_send_sge = max_send_sge;
+       if (my_qp->send_cq)
+               parms.send_cq_handle = my_qp->send_cq->ipz_cq_handle;
+       if (my_qp->recv_cq)
+               parms.recv_cq_handle = my_qp->recv_cq->ipz_cq_handle;
 
-       h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, my_qp, &parms);
+       parms.max_send_wr = init_attr->cap.max_send_wr;
+       parms.max_recv_wr = init_attr->cap.max_recv_wr;
+       parms.max_send_sge = max_send_sge;
+       parms.max_recv_sge = max_recv_sge;
 
+       h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms);
        if (h_ret != H_SUCCESS) {
                ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lx",
                         h_ret);
@@ -523,18 +565,20 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
                goto create_qp_exit1;
        }
 
-       my_qp->ib_qp.qp_num = my_qp->real_qp_num;
+       ib_qp_num = my_qp->real_qp_num = parms.real_qp_num;
+       my_qp->ipz_qp_handle = parms.qp_handle;
+       my_qp->galpas = parms.galpas;
 
-       switch (init_attr->qp_type) {
+       switch (qp_type) {
        case IB_QPT_RC:
-               if (isdaqp == 0) {
+               if (!is_llqp) {
                        swqe_size = offsetof(struct ehca_wqe, u.nud.sg_list[
                                             (parms.act_nr_send_sges)]);
                        rwqe_size = offsetof(struct ehca_wqe, u.nud.sg_list[
                                             (parms.act_nr_recv_sges)]);
-               } else { /* for daqp we need to use msg size, not wqe size */
-                       swqe_size = da_rc_msg_size[max_send_sge];
-                       rwqe_size = da_rc_msg_size[max_recv_sge];
+               } else { /* for LLQP we need to use msg size, not wqe size */
+                       swqe_size = ll_qp_msg_size(max_send_sge);
+                       rwqe_size = ll_qp_msg_size(max_recv_sge);
                        parms.act_nr_send_sges = 1;
                        parms.act_nr_recv_sges = 1;
                }
@@ -549,29 +593,27 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
        case IB_QPT_UD:
        case IB_QPT_GSI:
        case IB_QPT_SMI:
-               /* UD circumvention */
-               parms.act_nr_recv_sges -= 2;
-               parms.act_nr_send_sges -= 2;
-               if (isdaqp) {
-                       swqe_size = da_ud_sq_msg_size[max_send_sge];
-                       rwqe_size = da_rc_msg_size[max_recv_sge];
+               if (is_llqp) {
+                       swqe_size = ll_qp_msg_size(parms.act_nr_send_sges);
+                       rwqe_size = ll_qp_msg_size(parms.act_nr_recv_sges);
                        parms.act_nr_send_sges = 1;
                        parms.act_nr_recv_sges = 1;
                } else {
+                       /* UD circumvention */
+                       parms.act_nr_send_sges -= 2;
+                       parms.act_nr_recv_sges -= 2;
                        swqe_size = offsetof(struct ehca_wqe,
                                             u.ud_av.sg_list[parms.act_nr_send_sges]);
                        rwqe_size = offsetof(struct ehca_wqe,
                                             u.ud_av.sg_list[parms.act_nr_recv_sges]);
                }
 
-               if (IB_QPT_GSI == init_attr->qp_type ||
-                   IB_QPT_SMI == init_attr->qp_type) {
+               if (IB_QPT_GSI == qp_type || IB_QPT_SMI == qp_type) {
                        parms.act_nr_send_wqes = init_attr->cap.max_send_wr;
                        parms.act_nr_recv_wqes = init_attr->cap.max_recv_wr;
                        parms.act_nr_send_sges = init_attr->cap.max_send_sge;
                        parms.act_nr_recv_sges = init_attr->cap.max_recv_sge;
-                       my_qp->ib_qp.qp_num =
-                               (init_attr->qp_type == IB_QPT_SMI) ? 0 : 1;
+                       ib_qp_num = (qp_type == IB_QPT_SMI) ? 0 : 1;
                }
 
                break;
@@ -580,108 +622,234 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
                break;
        }
 
-       /* initializes r/squeue and registers queue pages */
-       ret = init_qp_queues(shca, my_qp,
-                            parms.nr_sq_pages, parms.nr_rq_pages,
-                            swqe_size, rwqe_size,
-                            parms.act_nr_send_sges, parms.act_nr_recv_sges);
-       if (ret) {
-               ehca_err(pd->device,
-                        "Couldn't initialize r/squeue and pages ret=%x", ret);
-               goto create_qp_exit2;
+       /* initialize r/squeue and register queue pages */
+       if (HAS_SQ(my_qp)) {
+               ret = init_qp_queue(
+                       shca, my_qp, &my_qp->ipz_squeue, 0,
+                       HAS_RQ(my_qp) ? H_PAGE_REGISTERED : H_SUCCESS,
+                       parms.nr_sq_pages, swqe_size,
+                       parms.act_nr_send_sges);
+               if (ret) {
+                       ehca_err(pd->device, "Couldn't initialize squeue "
+                                "and pages  ret=%x", ret);
+                       goto create_qp_exit2;
+               }
        }
 
-       my_qp->ib_qp.pd = &my_pd->ib_pd;
-       my_qp->ib_qp.device = my_pd->ib_pd.device;
+       if (HAS_RQ(my_qp)) {
+               ret = init_qp_queue(
+                       shca, my_qp, &my_qp->ipz_rqueue, 1,
+                       H_SUCCESS, parms.nr_rq_pages, rwqe_size,
+                       parms.act_nr_recv_sges);
+               if (ret) {
+                       ehca_err(pd->device, "Couldn't initialize rqueue "
+                                "and pages ret=%x", ret);
+                       goto create_qp_exit3;
+               }
+       }
 
-       my_qp->ib_qp.recv_cq = init_attr->recv_cq;
-       my_qp->ib_qp.send_cq = init_attr->send_cq;
+       if (is_srq) {
+               my_qp->ib_srq.pd = &my_pd->ib_pd;
+               my_qp->ib_srq.device = my_pd->ib_pd.device;
 
-       my_qp->ib_qp.qp_type = init_attr->qp_type;
+               my_qp->ib_srq.srq_context = init_attr->qp_context;
+               my_qp->ib_srq.event_handler = init_attr->event_handler;
+       } else {
+               my_qp->ib_qp.qp_num = ib_qp_num;
+               my_qp->ib_qp.pd = &my_pd->ib_pd;
+               my_qp->ib_qp.device = my_pd->ib_pd.device;
+
+               my_qp->ib_qp.recv_cq = init_attr->recv_cq;
+               my_qp->ib_qp.send_cq = init_attr->send_cq;
 
-       my_qp->qp_type = init_attr->qp_type;
-       my_qp->ib_qp.srq = init_attr->srq;
+               my_qp->ib_qp.qp_type = qp_type;
+               my_qp->ib_qp.srq = init_attr->srq;
 
-       my_qp->ib_qp.qp_context = init_attr->qp_context;
-       my_qp->ib_qp.event_handler = init_attr->event_handler;
+               my_qp->ib_qp.qp_context = init_attr->qp_context;
+               my_qp->ib_qp.event_handler = init_attr->event_handler;
+       }
 
        init_attr->cap.max_inline_data = 0; /* not supported yet */
        init_attr->cap.max_recv_sge = parms.act_nr_recv_sges;
        init_attr->cap.max_recv_wr = parms.act_nr_recv_wqes;
        init_attr->cap.max_send_sge = parms.act_nr_send_sges;
        init_attr->cap.max_send_wr = parms.act_nr_send_wqes;
+       my_qp->init_attr = *init_attr;
 
        /* NOTE: define_apq0() not supported yet */
-       if (init_attr->qp_type == IB_QPT_GSI) {
+       if (qp_type == IB_QPT_GSI) {
                h_ret = ehca_define_sqp(shca, my_qp, init_attr);
                if (h_ret != H_SUCCESS) {
                        ehca_err(pd->device, "ehca_define_sqp() failed rc=%lx",
                                 h_ret);
                        ret = ehca2ib_return_code(h_ret);
-                       goto create_qp_exit3;
+                       goto create_qp_exit4;
                }
        }
-       if (init_attr->send_cq) {
-               struct ehca_cq *cq = container_of(init_attr->send_cq,
-                                                 struct ehca_cq, ib_cq);
-               ret = ehca_cq_assign_qp(cq, my_qp);
+
+       if (my_qp->send_cq) {
+               ret = ehca_cq_assign_qp(my_qp->send_cq, my_qp);
                if (ret) {
                        ehca_err(pd->device, "Couldn't assign qp to send_cq ret=%x",
                                 ret);
-                       goto create_qp_exit3;
+                       goto create_qp_exit4;
                }
-               my_qp->send_cq = cq;
        }
+
        /* copy queues, galpa data to user space */
        if (context && udata) {
-               struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue;
-               struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue;
                struct ehca_create_qp_resp resp;
                memset(&resp, 0, sizeof(resp));
 
                resp.qp_num = my_qp->real_qp_num;
                resp.token = my_qp->token;
                resp.qp_type = my_qp->qp_type;
+               resp.ext_type = my_qp->ext_type;
                resp.qkey = my_qp->qkey;
                resp.real_qp_num = my_qp->real_qp_num;
-               /* rqueue properties */
-               resp.ipz_rqueue.qe_size = ipz_rqueue->qe_size;
-               resp.ipz_rqueue.act_nr_of_sg = ipz_rqueue->act_nr_of_sg;
-               resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length;
-               resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize;
-               resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state;
-               /* squeue properties */
-               resp.ipz_squeue.qe_size = ipz_squeue->qe_size;
-               resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg;
-               resp.ipz_squeue.queue_length = ipz_squeue->queue_length;
-               resp.ipz_squeue.pagesize = ipz_squeue->pagesize;
-               resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state;
+               if (HAS_SQ(my_qp))
+                       queue2resp(&resp.ipz_squeue, &my_qp->ipz_squeue);
+               if (HAS_RQ(my_qp))
+                       queue2resp(&resp.ipz_rqueue, &my_qp->ipz_rqueue);
+
                if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
                        ehca_err(pd->device, "Copy to udata failed");
                        ret = -EINVAL;
-                       goto create_qp_exit3;
+                       goto create_qp_exit4;
                }
        }
 
-       return &my_qp->ib_qp;
+       return my_qp;
+
+create_qp_exit4:
+       if (HAS_RQ(my_qp))
+               ipz_queue_dtor(&my_qp->ipz_rqueue);
 
 create_qp_exit3:
-       ipz_queue_dtor(&my_qp->ipz_rqueue);
-       ipz_queue_dtor(&my_qp->ipz_squeue);
+       if (HAS_SQ(my_qp))
+               ipz_queue_dtor(&my_qp->ipz_squeue);
 
 create_qp_exit2:
        hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
 
 create_qp_exit1:
-       spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+       write_lock_irqsave(&ehca_qp_idr_lock, flags);
        idr_remove(&ehca_qp_idr, my_qp->token);
-       spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+       write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
 
 create_qp_exit0:
        kmem_cache_free(qp_cache, my_qp);
        return ERR_PTR(ret);
 }
 
+struct ib_qp *ehca_create_qp(struct ib_pd *pd,
+                            struct ib_qp_init_attr *qp_init_attr,
+                            struct ib_udata *udata)
+{
+       struct ehca_qp *ret;
+
+       ret = internal_create_qp(pd, qp_init_attr, NULL, udata, 0);
+       return IS_ERR(ret) ? (struct ib_qp *) ret : &ret->ib_qp;
+}
+
+int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+                       struct ib_uobject *uobject);
+
+struct ib_srq *ehca_create_srq(struct ib_pd *pd,
+                              struct ib_srq_init_attr *srq_init_attr,
+                              struct ib_udata *udata)
+{
+       struct ib_qp_init_attr qp_init_attr;
+       struct ehca_qp *my_qp;
+       struct ib_srq *ret;
+       struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
+                                             ib_device);
+       struct hcp_modify_qp_control_block *mqpcb;
+       u64 hret, update_mask;
+
+       /* For common attributes, internal_create_qp() takes its info
+        * out of qp_init_attr, so copy all common attrs there.
+        */
+       memset(&qp_init_attr, 0, sizeof(qp_init_attr));
+       qp_init_attr.event_handler = srq_init_attr->event_handler;
+       qp_init_attr.qp_context = srq_init_attr->srq_context;
+       qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;
+       qp_init_attr.qp_type = IB_QPT_RC;
+       qp_init_attr.cap.max_recv_wr = srq_init_attr->attr.max_wr;
+       qp_init_attr.cap.max_recv_sge = srq_init_attr->attr.max_sge;
+
+       my_qp = internal_create_qp(pd, &qp_init_attr, srq_init_attr, udata, 1);
+       if (IS_ERR(my_qp))
+               return (struct ib_srq *) my_qp;
+
+       /* copy back return values */
+       srq_init_attr->attr.max_wr = qp_init_attr.cap.max_recv_wr;
+       srq_init_attr->attr.max_sge = qp_init_attr.cap.max_recv_sge;
+
+       /* drive SRQ into RTR state */
+       mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!mqpcb) {
+               ehca_err(pd->device, "Could not get zeroed page for mqpcb "
+                        "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num);
+               ret = ERR_PTR(-ENOMEM);
+               goto create_srq1;
+       }
+
+       mqpcb->qp_state = EHCA_QPS_INIT;
+       mqpcb->prim_phys_port = 1;
+       update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
+       hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+                               my_qp->ipz_qp_handle,
+                               &my_qp->pf,
+                               update_mask,
+                               mqpcb, my_qp->galpas.kernel);
+       if (hret != H_SUCCESS) {
+               ehca_err(pd->device, "Could not modify SRQ to INIT"
+                        "ehca_qp=%p qp_num=%x hret=%lx",
+                        my_qp, my_qp->real_qp_num, hret);
+               goto create_srq2;
+       }
+
+       mqpcb->qp_enable = 1;
+       update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1);
+       hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+                               my_qp->ipz_qp_handle,
+                               &my_qp->pf,
+                               update_mask,
+                               mqpcb, my_qp->galpas.kernel);
+       if (hret != H_SUCCESS) {
+               ehca_err(pd->device, "Could not enable SRQ"
+                        "ehca_qp=%p qp_num=%x hret=%lx",
+                        my_qp, my_qp->real_qp_num, hret);
+               goto create_srq2;
+       }
+
+       mqpcb->qp_state  = EHCA_QPS_RTR;
+       update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
+       hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+                               my_qp->ipz_qp_handle,
+                               &my_qp->pf,
+                               update_mask,
+                               mqpcb, my_qp->galpas.kernel);
+       if (hret != H_SUCCESS) {
+               ehca_err(pd->device, "Could not modify SRQ to RTR"
+                        "ehca_qp=%p qp_num=%x hret=%lx",
+                        my_qp, my_qp->real_qp_num, hret);
+               goto create_srq2;
+       }
+
+       return &my_qp->ib_srq;
+
+create_srq2:
+       ret = ERR_PTR(ehca2ib_return_code(hret));
+       ehca_free_fw_ctrlblock(mqpcb);
+
+create_srq1:
+       internal_destroy_qp(pd->device, my_qp, my_qp->ib_srq.uobject);
+
+       return ret;
+}
+
 /*
  * prepare_sqe_rts called by internal_modify_qp() at trans sqe -> rts
  * set purge bit of bad wqe and subsequent wqes to avoid reentering sqe
@@ -765,7 +933,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
        u64 h_ret;
        int bad_wqe_cnt = 0;
        int squeue_locked = 0;
-       unsigned long spl_flags = 0;
+       unsigned long flags = 0;
 
        /* do query_qp to obtain current attr values */
        mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
@@ -886,6 +1054,17 @@ static int internal_modify_qp(struct ib_qp *ibqp,
                 "ehca_qp=%p qp_num=%x <VALID STATE CHANGE> qp_state_xsit=%x",
                 my_qp, ibqp->qp_num, statetrans);
 
+       /* eHCA2 rev2 and higher require the SEND_GRH_FLAG to be set
+        * in non-LL UD QPs.
+        */
+       if ((my_qp->qp_type == IB_QPT_UD) &&
+           (my_qp->ext_type != EQPT_LLQP) &&
+           (statetrans == IB_QPST_INIT2RTR) &&
+           (shca->hw_level >= 0x22)) {
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);
+               mqpcb->send_grh_flag = 1;
+       }
+
        /* sqe -> rts: set purge bit of bad wqe before actual trans */
        if ((my_qp->qp_type == IB_QPT_UD ||
             my_qp->qp_type == IB_QPT_GSI ||
@@ -895,7 +1074,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
                if (!ibqp->uobject) {
                        struct ehca_wqe *wqe;
                        /* lock send queue */
-                       spin_lock_irqsave(&my_qp->spinlock_s, spl_flags);
+                       spin_lock_irqsave(&my_qp->spinlock_s, flags);
                        squeue_locked = 1;
                        /* mark next free wqe */
                        wqe = (struct ehca_wqe*)
@@ -1181,7 +1360,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
 
 modify_qp_exit2:
        if (squeue_locked) { /* this means: sqe -> rts */
-               spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags);
+               spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
                my_qp->sqerr_purgeflag = 1;
        }
 
@@ -1312,6 +1491,9 @@ int ehca_query_qp(struct ib_qp *qp,
        qp_attr->alt_port_num = qpcb->alt_phys_port;
        qp_attr->alt_timeout = qpcb->timeout_al;
 
+       qp_attr->max_dest_rd_atomic = qpcb->rdma_nr_atomic_resp_res;
+       qp_attr->max_rd_atomic = qpcb->rdma_atomic_outst_dest_qp;
+
        /* primary av */
        qp_attr->ah_attr.sl = qpcb->service_level;
 
@@ -1367,53 +1549,170 @@ query_qp_exit1:
        return ret;
 }
 
-int ehca_destroy_qp(struct ib_qp *ibqp)
+int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+                   enum ib_srq_attr_mask attr_mask, struct ib_udata *udata)
 {
-       struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
-       struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
+       struct ehca_qp *my_qp =
+               container_of(ibsrq, struct ehca_qp, ib_srq);
+       struct ehca_pd *my_pd =
+               container_of(ibsrq->pd, struct ehca_pd, ib_pd);
+       struct ehca_shca *shca =
+               container_of(ibsrq->pd->device, struct ehca_shca, ib_device);
+       struct hcp_modify_qp_control_block *mqpcb;
+       u64 update_mask;
+       u64 h_ret;
+       int ret = 0;
+
+       u32 cur_pid = current->tgid;
+       if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+           my_pd->ownpid != cur_pid) {
+               ehca_err(ibsrq->pd->device, "Invalid caller pid=%x ownpid=%x",
+                        cur_pid, my_pd->ownpid);
+               return -EINVAL;
+       }
+
+       mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!mqpcb) {
+               ehca_err(ibsrq->device, "Could not get zeroed page for mqpcb "
+                        "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num);
+               return -ENOMEM;
+       }
+
+       update_mask = 0;
+       if (attr_mask & IB_SRQ_LIMIT) {
+               attr_mask &= ~IB_SRQ_LIMIT;
+               update_mask |=
+                       EHCA_BMASK_SET(MQPCB_MASK_CURR_SRQ_LIMIT, 1)
+                       | EHCA_BMASK_SET(MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG, 1);
+               mqpcb->curr_srq_limit =
+                       EHCA_BMASK_SET(MQPCB_CURR_SRQ_LIMIT, attr->srq_limit);
+               mqpcb->qp_aff_asyn_ev_log_reg =
+                       EHCA_BMASK_SET(QPX_AAELOG_RESET_SRQ_LIMIT, 1);
+       }
+
+       /* by now, all bits in attr_mask should have been cleared */
+       if (attr_mask) {
+               ehca_err(ibsrq->device, "invalid attribute mask bits set  "
+                        "attr_mask=%x", attr_mask);
+               ret = -EINVAL;
+               goto modify_srq_exit0;
+       }
+
+       if (ehca_debug_level)
+               ehca_dmp(mqpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
+
+       h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, my_qp->ipz_qp_handle,
+                                NULL, update_mask, mqpcb,
+                                my_qp->galpas.kernel);
+
+       if (h_ret != H_SUCCESS) {
+               ret = ehca2ib_return_code(h_ret);
+               ehca_err(ibsrq->device, "hipz_h_modify_qp() failed rc=%lx "
+                        "ehca_qp=%p qp_num=%x",
+                        h_ret, my_qp, my_qp->real_qp_num);
+       }
+
+modify_srq_exit0:
+       ehca_free_fw_ctrlblock(mqpcb);
+
+       return ret;
+}
+
+int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
+{
+       struct ehca_qp *my_qp = container_of(srq, struct ehca_qp, ib_srq);
+       struct ehca_pd *my_pd = container_of(srq->pd, struct ehca_pd, ib_pd);
+       struct ehca_shca *shca = container_of(srq->device, struct ehca_shca,
                                              ib_device);
+       struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+       struct hcp_modify_qp_control_block *qpcb;
+       u32 cur_pid = current->tgid;
+       int ret = 0;
+       u64 h_ret;
+
+       if (my_pd->ib_pd.uobject  && my_pd->ib_pd.uobject->context  &&
+           my_pd->ownpid != cur_pid) {
+               ehca_err(srq->device, "Invalid caller pid=%x ownpid=%x",
+                        cur_pid, my_pd->ownpid);
+               return -EINVAL;
+       }
+
+       qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!qpcb) {
+               ehca_err(srq->device, "Out of memory for qpcb "
+                        "ehca_qp=%p qp_num=%x", my_qp, my_qp->real_qp_num);
+               return -ENOMEM;
+       }
+
+       h_ret = hipz_h_query_qp(adapter_handle, my_qp->ipz_qp_handle,
+                               NULL, qpcb, my_qp->galpas.kernel);
+
+       if (h_ret != H_SUCCESS) {
+               ret = ehca2ib_return_code(h_ret);
+               ehca_err(srq->device, "hipz_h_query_qp() failed "
+                        "ehca_qp=%p qp_num=%x h_ret=%lx",
+                        my_qp, my_qp->real_qp_num, h_ret);
+               goto query_srq_exit1;
+       }
+
+       srq_attr->max_wr = qpcb->max_nr_outst_recv_wr - 1;
+       srq_attr->srq_limit = EHCA_BMASK_GET(
+               MQPCB_CURR_SRQ_LIMIT, qpcb->curr_srq_limit);
+
+       if (ehca_debug_level)
+               ehca_dmp(qpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
+
+query_srq_exit1:
+       ehca_free_fw_ctrlblock(qpcb);
+
+       return ret;
+}
+
+int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+                       struct ib_uobject *uobject)
+{
+       struct ehca_shca *shca = container_of(dev, struct ehca_shca, ib_device);
        struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
                                             ib_pd);
        u32 cur_pid = current->tgid;
-       u32 qp_num = ibqp->qp_num;
+       u32 qp_num = my_qp->real_qp_num;
        int ret;
        u64 h_ret;
        u8 port_num;
        enum ib_qp_type qp_type;
        unsigned long flags;
 
-       if (ibqp->uobject) {
+       if (uobject) {
                if (my_qp->mm_count_galpa ||
                    my_qp->mm_count_rqueue || my_qp->mm_count_squeue) {
-                       ehca_err(ibqp->device, "Resources still referenced in "
-                                "user space qp_num=%x", ibqp->qp_num);
+                       ehca_err(dev, "Resources still referenced in "
+                                "user space qp_num=%x", qp_num);
                        return -EINVAL;
                }
                if (my_pd->ownpid != cur_pid) {
-                       ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x",
+                       ehca_err(dev, "Invalid caller pid=%x ownpid=%x",
                                 cur_pid, my_pd->ownpid);
                        return -EINVAL;
                }
        }
 
        if (my_qp->send_cq) {
-               ret = ehca_cq_unassign_qp(my_qp->send_cq,
-                                             my_qp->real_qp_num);
+               ret = ehca_cq_unassign_qp(my_qp->send_cq, qp_num);
                if (ret) {
-                       ehca_err(ibqp->device, "Couldn't unassign qp from "
+                       ehca_err(dev, "Couldn't unassign qp from "
                                 "send_cq ret=%x qp_num=%x cq_num=%x", ret,
-                                my_qp->ib_qp.qp_num, my_qp->send_cq->cq_number);
+                                qp_num, my_qp->send_cq->cq_number);
                        return ret;
                }
        }
 
-       spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+       write_lock_irqsave(&ehca_qp_idr_lock, flags);
        idr_remove(&ehca_qp_idr, my_qp->token);
-       spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+       write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
 
        h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
        if (h_ret != H_SUCCESS) {
-               ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx "
+               ehca_err(dev, "hipz_h_destroy_qp() failed rc=%lx "
                         "ehca_qp=%p qp_num=%x", h_ret, my_qp, qp_num);
                return ehca2ib_return_code(h_ret);
        }
@@ -1424,7 +1723,7 @@ int ehca_destroy_qp(struct ib_qp *ibqp)
        /* no support for IB_QPT_SMI yet */
        if (qp_type == IB_QPT_GSI) {
                struct ib_event event;
-               ehca_info(ibqp->device, "device %s: port %x is inactive.",
+               ehca_info(dev, "device %s: port %x is inactive.",
                          shca->ib_device.name, port_num);
                event.device = &shca->ib_device;
                event.event = IB_EVENT_PORT_ERR;
@@ -1433,12 +1732,28 @@ int ehca_destroy_qp(struct ib_qp *ibqp)
                ib_dispatch_event(&event);
        }
 
-       ipz_queue_dtor(&my_qp->ipz_rqueue);
-       ipz_queue_dtor(&my_qp->ipz_squeue);
+       if (HAS_RQ(my_qp))
+               ipz_queue_dtor(&my_qp->ipz_rqueue);
+       if (HAS_SQ(my_qp))
+               ipz_queue_dtor(&my_qp->ipz_squeue);
        kmem_cache_free(qp_cache, my_qp);
        return 0;
 }
 
+int ehca_destroy_qp(struct ib_qp *qp)
+{
+       return internal_destroy_qp(qp->device,
+                                  container_of(qp, struct ehca_qp, ib_qp),
+                                  qp->uobject);
+}
+
+int ehca_destroy_srq(struct ib_srq *srq)
+{
+       return internal_destroy_qp(srq->device,
+                                  container_of(srq, struct ehca_qp, ib_srq),
+                                  srq->uobject);
+}
+
 int ehca_init_qp_cache(void)
 {
        qp_cache = kmem_cache_create("ehca_cache_qp",
index caec9dee09e1b0df65a0e03fed29d2e16324d4c3..61da65e6e5e09957868d2097808d77ad809b5baf 100644 (file)
@@ -3,8 +3,9 @@
  *
  *  post_send/recv, poll_cq, req_notify
  *
- *  Authors: Waleri Fomin <fomin@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *  Authors: Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Waleri Fomin <fomin@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
  *           Reinhard Ernst <rernst@de.ibm.com>
  *
  *  Copyright (c) 2005 IBM Corporation
@@ -362,10 +363,10 @@ int ehca_post_send(struct ib_qp *qp,
        struct ehca_wqe *wqe_p;
        int wqe_cnt = 0;
        int ret = 0;
-       unsigned long spl_flags;
+       unsigned long flags;
 
        /* LOCK the QUEUE */
-       spin_lock_irqsave(&my_qp->spinlock_s, spl_flags);
+       spin_lock_irqsave(&my_qp->spinlock_s, flags);
 
        /* loop processes list of send reqs */
        for (cur_send_wr = send_wr; cur_send_wr != NULL;
@@ -406,26 +407,31 @@ int ehca_post_send(struct ib_qp *qp,
        } /* eof for cur_send_wr */
 
 post_send_exit0:
-       /* UNLOCK the QUEUE */
-       spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags);
        iosync(); /* serialize GAL register access */
        hipz_update_sqa(my_qp, wqe_cnt);
+       spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
        return ret;
 }
 
-int ehca_post_recv(struct ib_qp *qp,
-                  struct ib_recv_wr *recv_wr,
-                  struct ib_recv_wr **bad_recv_wr)
+static int internal_post_recv(struct ehca_qp *my_qp,
+                             struct ib_device *dev,
+                             struct ib_recv_wr *recv_wr,
+                             struct ib_recv_wr **bad_recv_wr)
 {
-       struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
        struct ib_recv_wr *cur_recv_wr;
        struct ehca_wqe *wqe_p;
        int wqe_cnt = 0;
        int ret = 0;
-       unsigned long spl_flags;
+       unsigned long flags;
+
+       if (unlikely(!HAS_RQ(my_qp))) {
+               ehca_err(dev, "QP has no RQ  ehca_qp=%p qp_num=%x ext_type=%d",
+                        my_qp, my_qp->real_qp_num, my_qp->ext_type);
+               return -ENODEV;
+       }
 
        /* LOCK the QUEUE */
-       spin_lock_irqsave(&my_qp->spinlock_r, spl_flags);
+       spin_lock_irqsave(&my_qp->spinlock_r, flags);
 
        /* loop processes list of send reqs */
        for (cur_recv_wr = recv_wr; cur_recv_wr != NULL;
@@ -439,8 +445,8 @@ int ehca_post_recv(struct ib_qp *qp,
                                *bad_recv_wr = cur_recv_wr;
                        if (wqe_cnt == 0) {
                                ret = -ENOMEM;
-                               ehca_err(qp->device, "Too many posted WQEs "
-                                        "qp_num=%x", qp->qp_num);
+                               ehca_err(dev, "Too many posted WQEs "
+                                        "qp_num=%x", my_qp->real_qp_num);
                        }
                        goto post_recv_exit0;
                }
@@ -455,23 +461,39 @@ int ehca_post_recv(struct ib_qp *qp,
                        *bad_recv_wr = cur_recv_wr;
                        if (wqe_cnt == 0) {
                                ret = -EINVAL;
-                               ehca_err(qp->device, "Could not write WQE "
-                                        "qp_num=%x", qp->qp_num);
+                               ehca_err(dev, "Could not write WQE "
+                                        "qp_num=%x", my_qp->real_qp_num);
                        }
                        goto post_recv_exit0;
                }
                wqe_cnt++;
-               ehca_gen_dbg("ehca_qp=%p qp_num=%x wqe_cnt=%d",
-                    my_qp, qp->qp_num, wqe_cnt);
+               ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d",
+                        my_qp, my_qp->real_qp_num, wqe_cnt);
        } /* eof for cur_recv_wr */
 
 post_recv_exit0:
-       spin_unlock_irqrestore(&my_qp->spinlock_r, spl_flags);
        iosync(); /* serialize GAL register access */
        hipz_update_rqa(my_qp, wqe_cnt);
+       spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
        return ret;
 }
 
+int ehca_post_recv(struct ib_qp *qp,
+                  struct ib_recv_wr *recv_wr,
+                  struct ib_recv_wr **bad_recv_wr)
+{
+       return internal_post_recv(container_of(qp, struct ehca_qp, ib_qp),
+                                 qp->device, recv_wr, bad_recv_wr);
+}
+
+int ehca_post_srq_recv(struct ib_srq *srq,
+                      struct ib_recv_wr *recv_wr,
+                      struct ib_recv_wr **bad_recv_wr)
+{
+       return internal_post_recv(container_of(srq, struct ehca_qp, ib_srq),
+                                 srq->device, recv_wr, bad_recv_wr);
+}
+
 /*
  * ib_wc_opcode table converts ehca wc opcode to ib
  * Since we use zero to indicate invalid opcode, the actual ib opcode must
@@ -494,6 +516,7 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
        int ret = 0;
        struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
        struct ehca_cqe *cqe;
+       struct ehca_qp *my_qp;
        int cqe_count = 0;
 
 poll_cq_one_read_cqe:
@@ -513,7 +536,7 @@ poll_cq_one_read_cqe:
        if (unlikely(cqe->status & WC_STATUS_PURGE_BIT)) {
                struct ehca_qp *qp=ehca_cq_get_qp(my_cq, cqe->local_qp_number);
                int purgeflag;
-               unsigned long spl_flags;
+               unsigned long flags;
                if (!qp) {
                        ehca_err(cq->device, "cq_num=%x qp_num=%x "
                                 "could not find qp -> ignore cqe",
@@ -523,9 +546,9 @@ poll_cq_one_read_cqe:
                        /* ignore this purged cqe */
                        goto poll_cq_one_read_cqe;
                }
-               spin_lock_irqsave(&qp->spinlock_s, spl_flags);
+               spin_lock_irqsave(&qp->spinlock_s, flags);
                purgeflag = qp->sqerr_purgeflag;
-               spin_unlock_irqrestore(&qp->spinlock_s, spl_flags);
+               spin_unlock_irqrestore(&qp->spinlock_s, flags);
 
                if (purgeflag) {
                        ehca_dbg(cq->device, "Got CQE with purged bit qp_num=%x "
@@ -545,7 +568,7 @@ poll_cq_one_read_cqe:
        }
 
        /* tracing cqe */
-       if (ehca_debug_level) {
+       if (unlikely(ehca_debug_level)) {
                ehca_dbg(cq->device,
                         "Received COMPLETION ehca_cq=%p cq_num=%x -----",
                         my_cq, my_cq->cq_number);
@@ -579,7 +602,11 @@ poll_cq_one_read_cqe:
        } else
                wc->status = IB_WC_SUCCESS;
 
-       wc->qp = NULL;
+       read_lock(&ehca_qp_idr_lock);
+       my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
+       wc->qp = &my_qp->ib_qp;
+       read_unlock(&ehca_qp_idr_lock);
+
        wc->byte_len = cqe->nr_bytes_transferred;
        wc->pkey_index = cqe->pkey_index;
        wc->slid = cqe->rlid;
@@ -589,7 +616,7 @@ poll_cq_one_read_cqe:
        wc->imm_data = cpu_to_be32(cqe->immediate_data);
        wc->sl = cqe->service_level;
 
-       if (wc->status != IB_WC_SUCCESS)
+       if (unlikely(wc->status != IB_WC_SUCCESS))
                ehca_dbg(cq->device,
                         "ehca_cq=%p cq_num=%x WARNING unsuccessful cqe "
                         "OPType=%x status=%x qp_num=%x src_qp=%x wr_id=%lx "
@@ -610,7 +637,7 @@ int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
        int nr;
        struct ib_wc *current_wc = wc;
        int ret = 0;
-       unsigned long spl_flags;
+       unsigned long flags;
 
        if (num_entries < 1) {
                ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p "
@@ -619,14 +646,14 @@ int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
                goto poll_cq_exit0;
        }
 
-       spin_lock_irqsave(&my_cq->spinlock, spl_flags);
+       spin_lock_irqsave(&my_cq->spinlock, flags);
        for (nr = 0; nr < num_entries; nr++) {
                ret = ehca_poll_cq_one(cq, current_wc);
                if (ret)
                        break;
                current_wc++;
        } /* eof for nr */
-       spin_unlock_irqrestore(&my_cq->spinlock, spl_flags);
+       spin_unlock_irqrestore(&my_cq->spinlock, flags);
        if (ret == -EAGAIN  || !ret)
                ret = nr;
 
@@ -637,7 +664,6 @@ poll_cq_exit0:
 int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags)
 {
        struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
-       unsigned long spl_flags;
        int ret = 0;
 
        switch (notify_flags & IB_CQ_SOLICITED_MASK) {
@@ -652,6 +678,7 @@ int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags)
        }
 
        if (notify_flags & IB_CQ_REPORT_MISSED_EVENTS) {
+               unsigned long spl_flags;
                spin_lock_irqsave(&my_cq->spinlock, spl_flags);
                ret = ipz_qeit_is_valid(&my_cq->ipz_queue);
                spin_unlock_irqrestore(&my_cq->spinlock, spl_flags);
index 973c4b59154575fa9a0dad89864051183d848bc8..03b185f873dafb8c8641358efef02f9f1633dd0f 100644 (file)
@@ -59,6 +59,7 @@
 #include <linux/cpu.h>
 #include <linux/device.h>
 
+#include <asm/atomic.h>
 #include <asm/abs_addr.h>
 #include <asm/ibmebus.h>
 #include <asm/io.h>
index 73db920b6945e7b255f3ac2ac996ab87b42aa2de..3031b3bb56f9bc6b7ad3eb24d58d2b6d21f138ac 100644 (file)
@@ -253,16 +253,16 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
        u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */
        u32 cur_pid = current->tgid;
        u32 ret;
-       unsigned long flags;
        struct ehca_cq *cq;
        struct ehca_qp *qp;
        struct ehca_pd *pd;
+       struct ib_uobject *uobject;
 
        switch (q_type) {
        case  1: /* CQ */
-               spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+               read_lock(&ehca_cq_idr_lock);
                cq = idr_find(&ehca_cq_idr, idr_handle);
-               spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+               read_unlock(&ehca_cq_idr_lock);
 
                /* make sure this mmap really belongs to the authorized user */
                if (!cq)
@@ -288,9 +288,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
                break;
 
        case 2: /* QP */
-               spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+               read_lock(&ehca_qp_idr_lock);
                qp = idr_find(&ehca_qp_idr, idr_handle);
-               spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+               read_unlock(&ehca_qp_idr_lock);
 
                /* make sure this mmap really belongs to the authorized user */
                if (!qp)
@@ -304,7 +304,8 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
                        return -ENOMEM;
                }
 
-               if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context)
+               uobject = IS_SRQ(qp) ? qp->ib_srq.uobject : qp->ib_qp.uobject;
+               if (!uobject || uobject->context != context)
                        return -EINVAL;
 
                ret = ehca_mmap_qp(vma, qp, rsrc_type);
index 5766ae3a202995bebb306f4aae1f4580a888109a..4776a8b0feec4f02bbf6f90e8de04f79e0e9dbda 100644 (file)
@@ -5,6 +5,7 @@
  *
  *  Authors: Christoph Raisch <raisch@de.ibm.com>
  *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
  *           Gerd Bayer <gerd.bayer@de.ibm.com>
  *           Waleri Fomin <fomin@de.ibm.com>
  *
 #define H_ALL_RES_QP_MAX_SEND_SGE       EHCA_BMASK_IBM(32, 39)
 #define H_ALL_RES_QP_MAX_RECV_SGE       EHCA_BMASK_IBM(40, 47)
 
+#define H_ALL_RES_QP_UD_AV_LKEY         EHCA_BMASK_IBM(32, 63)
+#define H_ALL_RES_QP_SRQ_QP_TOKEN       EHCA_BMASK_IBM(0, 31)
+#define H_ALL_RES_QP_SRQ_QP_HANDLE      EHCA_BMASK_IBM(0, 64)
+#define H_ALL_RES_QP_SRQ_LIMIT          EHCA_BMASK_IBM(48, 63)
+#define H_ALL_RES_QP_SRQ_QPN            EHCA_BMASK_IBM(40, 63)
+
 #define H_ALL_RES_QP_ACT_OUTST_SEND_WR  EHCA_BMASK_IBM(16, 31)
 #define H_ALL_RES_QP_ACT_OUTST_RECV_WR  EHCA_BMASK_IBM(48, 63)
 #define H_ALL_RES_QP_ACT_SEND_SGE       EHCA_BMASK_IBM(8, 15)
 #define H_MP_SHUTDOWN                   EHCA_BMASK_IBM(48, 48)
 #define H_MP_RESET_QKEY_CTR             EHCA_BMASK_IBM(49, 49)
 
-/* direct access qp controls */
-#define DAQP_CTRL_ENABLE    0x01
-#define DAQP_CTRL_SEND_COMP 0x20
-#define DAQP_CTRL_RECV_COMP 0x40
+static DEFINE_SPINLOCK(hcall_lock);
 
 static u32 get_longbusy_msecs(int longbusy_rc)
 {
@@ -155,7 +159,7 @@ static long ehca_plpar_hcall9(unsigned long opcode,
 {
        long ret;
        int i, sleep_msecs, lock_is_set = 0;
-       unsigned long flags;
+       unsigned long flags = 0;
 
        ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
                     "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
@@ -284,53 +288,53 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
 }
 
 u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
-                            struct ehca_qp *qp,
                             struct ehca_alloc_qp_parms *parms)
 {
        u64 ret;
-       u64 allocate_controls;
-       u64 max_r10_reg;
+       u64 allocate_controls, max_r10_reg, r11, r12;
        u64 outs[PLPAR_HCALL9_BUFSIZE];
-       u16 max_nr_receive_wqes = qp->init_attr.cap.max_recv_wr + 1;
-       u16 max_nr_send_wqes = qp->init_attr.cap.max_send_wr + 1;
-       int daqp_ctrl = parms->daqp_ctrl;
 
        allocate_controls =
-               EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS,
-                              (daqp_ctrl & DAQP_CTRL_ENABLE) ? 1 : 0)
+               EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
                | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
                | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
                | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
                | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
-                                (daqp_ctrl & DAQP_CTRL_RECV_COMP) ? 1 : 0)
+                                !!(parms->ll_comp_flags & LLQP_RECV_COMP))
                | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
-                                (daqp_ctrl & DAQP_CTRL_SEND_COMP) ? 1 : 0)
+                                !!(parms->ll_comp_flags & LLQP_SEND_COMP))
                | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
                                 parms->ud_av_l_key_ctl)
                | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
 
        max_r10_reg =
                EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
-                              max_nr_send_wqes)
+                              parms->max_send_wr + 1)
                | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
-                                max_nr_receive_wqes)
+                                parms->max_recv_wr + 1)
                | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
                                 parms->max_send_sge)
                | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
                                 parms->max_recv_sge);
 
+       r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
+
+       if (parms->ext_type == EQPT_SRQ)
+               r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
+       else
+               r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
+
        ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
                                adapter_handle.handle,             /* r4  */
                                allocate_controls,                 /* r5  */
-                               qp->send_cq->ipz_cq_handle.handle,
-                               qp->recv_cq->ipz_cq_handle.handle,
-                               parms->ipz_eq_handle.handle,
-                               ((u64)qp->token << 32) | parms->pd.value,
-                               max_r10_reg,                       /* r10 */
-                               parms->ud_av_l_key_ctl,            /* r11 */
-                               0);
-       qp->ipz_qp_handle.handle = outs[0];
-       qp->real_qp_num = (u32)outs[1];
+                               parms->send_cq_handle.handle,
+                               parms->recv_cq_handle.handle,
+                               parms->eq_handle.handle,
+                               ((u64)parms->token << 32) | parms->pd.value,
+                               max_r10_reg, r11, r12);
+
+       parms->qp_handle.handle = outs[0];
+       parms->real_qp_num = (u32)outs[1];
        parms->act_nr_send_wqes =
                (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
        parms->act_nr_recv_wqes =
@@ -345,7 +349,7 @@ u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
                (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
 
        if (ret == H_SUCCESS)
-               hcp_galpas_ctor(&qp->galpas, outs[6], outs[6]);
+               hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
 
        if (ret == H_NOT_ENOUGH_RESOURCES)
                ehca_gen_err("Not enough resources. ret=%lx", ret);
index 2869f7dd61969415c1383cb357cdc7baeb4b4fde..60ce02b7066389e657c1ff7a33a9b8ee87b8120d 100644 (file)
@@ -78,7 +78,6 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
  * initialize resources, create empty QPPTs (2 rings).
  */
 u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
-                            struct ehca_qp *qp,
                             struct ehca_alloc_qp_parms *parms);
 
 u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
index fad91368dc5a7893237c3acebbf5eefa443aad28..dad6dea5636b55e1883eca6ac59e6f9248aafbd7 100644 (file)
@@ -163,6 +163,7 @@ struct hipz_qptemm {
 
 #define QPX_SQADDER EHCA_BMASK_IBM(48,63)
 #define QPX_RQADDER EHCA_BMASK_IBM(48,63)
+#define QPX_AAELOG_RESET_SRQ_LIMIT EHCA_BMASK_IBM(3,3)
 
 #define QPTEMM_OFFSET(x) offsetof(struct hipz_qptemm,x)
 
@@ -360,6 +361,24 @@ struct hipz_query_hca {
        u32 max_neq;
 } __attribute__ ((packed));
 
+#define HCA_CAP_AH_PORT_NR_CHECK      EHCA_BMASK_IBM( 0,  0)
+#define HCA_CAP_ATOMIC                EHCA_BMASK_IBM( 1,  1)
+#define HCA_CAP_AUTO_PATH_MIG         EHCA_BMASK_IBM( 2,  2)
+#define HCA_CAP_BAD_P_KEY_CTR         EHCA_BMASK_IBM( 3,  3)
+#define HCA_CAP_SQD_RTS_PORT_CHANGE   EHCA_BMASK_IBM( 4,  4)
+#define HCA_CAP_CUR_QP_STATE_MOD      EHCA_BMASK_IBM( 5,  5)
+#define HCA_CAP_INIT_TYPE             EHCA_BMASK_IBM( 6,  6)
+#define HCA_CAP_PORT_ACTIVE_EVENT     EHCA_BMASK_IBM( 7,  7)
+#define HCA_CAP_Q_KEY_VIOL_CTR        EHCA_BMASK_IBM( 8,  8)
+#define HCA_CAP_WQE_RESIZE            EHCA_BMASK_IBM( 9,  9)
+#define HCA_CAP_RAW_PACKET_MCAST      EHCA_BMASK_IBM(10, 10)
+#define HCA_CAP_SHUTDOWN_PORT         EHCA_BMASK_IBM(11, 11)
+#define HCA_CAP_RC_LL_QP              EHCA_BMASK_IBM(12, 12)
+#define HCA_CAP_SRQ                   EHCA_BMASK_IBM(13, 13)
+#define HCA_CAP_UD_LL_QP              EHCA_BMASK_IBM(16, 16)
+#define HCA_CAP_RESIZE_MR             EHCA_BMASK_IBM(17, 17)
+#define HCA_CAP_MINI_QP               EHCA_BMASK_IBM(18, 18)
+
 /* query port response block */
 struct hipz_query_port {
        u32 state;
index 57f141a36bceb2c6a5579ab4548f9d2c1cae3b2e..007f0882fd403a20805c988b2dd98e3ba0db1d07 100644 (file)
@@ -105,7 +105,6 @@ void *ipz_qpageit_get_inc(struct ipz_queue *queue);
  * step in struct ipz_queue, will wrap in ringbuffer
  * returns address (kv) of Queue Entry BEFORE increment
  * warning don't use in parallel with ipz_qpageit_get_inc()
- * warning unpredictable results may occur if steps>act_nr_of_queue_entries
  */
 static inline void *ipz_qeit_get_inc(struct ipz_queue *queue)
 {
@@ -120,32 +119,25 @@ static inline void *ipz_qeit_get_inc(struct ipz_queue *queue)
        return ret;
 }
 
+/*
+ * return a bool indicating whether current Queue Entry is valid
+ */
+static inline int ipz_qeit_is_valid(struct ipz_queue *queue)
+{
+       struct ehca_cqe *cqe = ipz_qeit_get(queue);
+       return ((cqe->cqe_flags >> 7) == (queue->toggle_state & 1));
+}
+
 /*
  * return current Queue Entry, increment Queue Entry iterator by one
  * step in struct ipz_queue, will wrap in ringbuffer
  * returns address (kv) of Queue Entry BEFORE increment
  * returns 0 and does not increment, if wrong valid state
  * warning don't use in parallel with ipz_qpageit_get_inc()
- * warning unpredictable results may occur if steps>act_nr_of_queue_entries
  */
 static inline void *ipz_qeit_get_inc_valid(struct ipz_queue *queue)
 {
-       struct ehca_cqe *cqe = ipz_qeit_get(queue);
-       u32 cqe_flags = cqe->cqe_flags;
-
-       if ((cqe_flags >> 7) != (queue->toggle_state & 1))
-               return NULL;
-
-       ipz_qeit_get_inc(queue);
-       return cqe;
-}
-
-static inline int ipz_qeit_is_valid(struct ipz_queue *queue)
-{
-       struct ehca_cqe *cqe = ipz_qeit_get(queue);
-       u32 cqe_flags = cqe->cqe_flags;
-
-       return cqe_flags >> 7 == (queue->toggle_state & 1);
+       return ipz_qeit_is_valid(queue) ? ipz_qeit_get_inc(queue) : NULL;
 }
 
 /*
index 90c14543677de94c1f1a74464d4bbe27ae6ef9cf..044da5828a787537b9744cf6401a06e48c4c00d2 100644 (file)
@@ -1,6 +1,6 @@
 config INFINIBAND_IPATH
        tristate "QLogic InfiniPath Driver"
-       depends on (PCI_MSI || HT_IRQ) && 64BIT && INFINIBAND && NET
+       depends on (PCI_MSI || HT_IRQ) && 64BIT && NET
        ---help---
        This is a driver for QLogic InfiniPath host channel adapters,
        including InfiniBand verbs support.  This driver allows these
index 10c008f22ba6947b9a5cf9c9d75f5cb976651452..b4b786d0dfcaaafff0af2bc45465c6b32984f3a7 100644 (file)
@@ -189,8 +189,7 @@ typedef enum _ipath_ureg {
 #define IPATH_RUNTIME_FORCE_WC_ORDER   0x4
 #define IPATH_RUNTIME_RCVHDR_COPY      0x8
 #define IPATH_RUNTIME_MASTER   0x10
-#define IPATH_RUNTIME_PBC_REWRITE 0x20
-#define IPATH_RUNTIME_LOOSE_DMA_ALIGN 0x40
+/* 0x20 and 0x40 are no longer used, but are reserved for ABI compatibility */
 
 /*
  * This structure is returned by ipath_userinit() immediately after
@@ -432,8 +431,15 @@ struct ipath_user_info {
 #define IPATH_CMD_UNUSED_1     25
 #define IPATH_CMD_UNUSED_2     26
 #define IPATH_CMD_PIOAVAILUPD  27      /* force an update of PIOAvail reg */
+#define IPATH_CMD_POLL_TYPE    28      /* set the kind of polling we want */
 
-#define IPATH_CMD_MAX          27
+#define IPATH_CMD_MAX          28
+
+/*
+ * Poll types
+ */
+#define IPATH_POLL_TYPE_URGENT  0x01
+#define IPATH_POLL_TYPE_OVERFLOW 0x02
 
 struct ipath_port_info {
        __u32 num_active;       /* number of active units */
@@ -474,6 +480,8 @@ struct ipath_cmd {
                __u16 part_key;
                /* user address of __u32 bitmask of active slaves */
                __u64 slave_mask_addr;
+               /* type of polling we want */
+               __u16 poll_type;
        } cmd;
 };
 
@@ -502,13 +510,30 @@ struct __ipath_sendpkt {
        struct ipath_iovec sps_iov[4];
 };
 
-/* Passed into diag data special file's ->write method. */
+/*
+ * diagnostics can send a packet by "writing" one of the following
+ * two structs to diag data special file
+ * The first is the legacy version for backward compatibility
+ */
 struct ipath_diag_pkt {
        __u32 unit;
        __u64 data;
        __u32 len;
 };
 
+/* The second diag_pkt struct is the expanded version that allows
+ * more control over the packet, specifically, by allowing a custom
+ * pbc (+ extra) qword, so that special modes and deliberate
+ * changes to CRCs can be used. The elements were also re-ordered
+ * for better alignment and to avoid padding issues.
+ */
+struct ipath_diag_xpkt {
+       __u64 data;
+       __u64 pbc_wd;
+       __u32 unit;
+       __u32 len;
+};
+
 /*
  * Data layout in I2C flash (for GUID, etc.)
  * All fields are little-endian binary unless otherwise stated
index 3e9241badba059859fe500cd53661c9ce3dbf693..a6f04d27ec576c021061df4d13d8f18e3fde61e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -90,6 +90,8 @@ void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited)
        wc->queue[head].sl = entry->sl;
        wc->queue[head].dlid_path_bits = entry->dlid_path_bits;
        wc->queue[head].port_num = entry->port_num;
+       /* Make sure queue entry is written before the head index. */
+       smp_wmb();
        wc->head = next;
 
        if (cq->notify == IB_CQ_NEXT_COMP ||
@@ -139,7 +141,8 @@ int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
 
                if (tail == wc->head)
                        break;
-
+               /* Make sure entry is read after head index is read. */
+               smp_rmb();
                qp = ipath_lookup_qpn(&to_idev(cq->ibcq.device)->qp_table,
                                      wc->queue[tail].qp_num);
                entry->qp = &qp->ibqp;
index 42bfbdb0d3e6af48abb11e411248afde6f850570..19c56e6491eb0c65183a7ff1a344cf5f4447d0e7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 63e8368b0e95260011a0ad8733624ce064d54f0a..a698f1949d1040da508c1c727acca8bf6bb24dbb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -323,13 +323,14 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
 {
        u32 __iomem *piobuf;
        u32 plen, clen, pbufn;
-       struct ipath_diag_pkt dp;
+       struct ipath_diag_pkt odp;
+       struct ipath_diag_xpkt dp;
        u32 *tmpbuf = NULL;
        struct ipath_devdata *dd;
        ssize_t ret = 0;
        u64 val;
 
-       if (count < sizeof(dp)) {
+       if (count != sizeof(dp)) {
                ret = -EINVAL;
                goto bail;
        }
@@ -339,6 +340,29 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
                goto bail;
        }
 
+       /*
+        * Due to padding/alignment issues (lessened with new struct)
+        * the old and new structs are the same length. We need to
+        * disambiguate them, which we can do because odp.len has never
+        * been less than the total of LRH+BTH+DETH so far, while
+        * dp.unit (same offset) unit is unlikely to get that high.
+        * Similarly, dp.data, the pointer to user at the same offset
+        * as odp.unit, is almost certainly at least one (512byte)page
+        * "above" NULL. The if-block below can be omitted if compatibility
+        * between a new driver and older diagnostic code is unimportant.
+        * compatibility the other direction (new diags, old driver) is
+        * handled in the diagnostic code, with a warning.
+        */
+       if (dp.unit >= 20 && dp.data < 512) {
+               /* very probable version mismatch. Fix it up */
+               memcpy(&odp, &dp, sizeof(odp));
+               /* We got a legacy dp, copy elements to dp */
+               dp.unit = odp.unit;
+               dp.data = odp.data;
+               dp.len = odp.len;
+               dp.pbc_wd = 0; /* Indicate we need to compute PBC wd */
+       }
+
        /* send count must be an exact number of dwords */
        if (dp.len & 3) {
                ret = -EINVAL;
@@ -371,9 +395,10 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
                ret = -ENODEV;
                goto bail;
        }
+       /* Check link state, but not if we have custom PBC */
        val = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
-       if (val != IPATH_IBSTATE_INIT && val != IPATH_IBSTATE_ARM &&
-           val != IPATH_IBSTATE_ACTIVE) {
+       if (!dp.pbc_wd && val != IPATH_IBSTATE_INIT &&
+               val != IPATH_IBSTATE_ARM && val != IPATH_IBSTATE_ACTIVE) {
                ipath_cdbg(VERBOSE, "unit %u not ready (state %llx)\n",
                           dd->ipath_unit, (unsigned long long) val);
                ret = -EINVAL;
@@ -419,9 +444,13 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
                ipath_cdbg(VERBOSE, "unit %u 0x%x+1w pio%d\n",
                           dd->ipath_unit, plen - 1, pbufn);
 
+       if (dp.pbc_wd == 0)
+               /* Legacy operation, use computed pbc_wd */
+               dp.pbc_wd = plen;
+
        /* we have to flush after the PBC for correctness on some cpus
         * or WC buffer can be written out of order */
-       writeq(plen, piobuf);
+       writeq(dp.pbc_wd, piobuf);
        ipath_flush_wc();
        /* copy all by the trigger word, then flush, so it's written
         * to chip before trigger word, then write trigger word, then
index e3a223209710bd7fa81a13798d18a8cb253f80be..9361f5ab8bd637f32dc6171ef0f5281f20b8c060 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -104,6 +104,9 @@ static int __devinit ipath_init_one(struct pci_dev *,
 #define PCI_DEVICE_ID_INFINIPATH_HT 0xd
 #define PCI_DEVICE_ID_INFINIPATH_PE800 0x10
 
+/* Number of seconds before our card status check...  */
+#define STATUS_TIMEOUT 60
+
 static const struct pci_device_id ipath_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) },
        { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_PE800) },
@@ -119,6 +122,18 @@ static struct pci_driver ipath_driver = {
        .id_table = ipath_pci_tbl,
 };
 
+static void ipath_check_status(struct work_struct *work)
+{
+       struct ipath_devdata *dd = container_of(work, struct ipath_devdata,
+                                               status_work.work);
+
+       /*
+        * If we don't have any interrupts, let the user know and
+        * don't bother checking again.
+        */
+       if (dd->ipath_int_counter == 0)
+               dev_err(&dd->pcidev->dev, "No interrupts detected.\n");
+}
 
 static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev,
                             u32 *bar0, u32 *bar1)
@@ -187,6 +202,8 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
        dd->pcidev = pdev;
        pci_set_drvdata(pdev, dd);
 
+       INIT_DELAYED_WORK(&dd->status_work, ipath_check_status);
+
        list_add(&dd->ipath_list, &ipath_dev_list);
 
 bail_unlock:
@@ -270,7 +287,6 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
        struct ipath_devdata *dd;
        unsigned long long addr;
        u32 bar0 = 0, bar1 = 0;
-       u8 rev;
 
        dd = ipath_alloc_devdata(pdev);
        if (IS_ERR(dd)) {
@@ -432,13 +448,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
        dd->ipath_deviceid = ent->device;       /* save for later use */
        dd->ipath_vendorid = ent->vendor;
 
-       ret = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-       if (ret) {
-               ipath_dev_err(dd, "Failed to read PCI revision ID unit "
-                             "%u: err %d\n", dd->ipath_unit, -ret);
-               goto bail_regions;      /* shouldn't ever happen */
-       }
-       dd->ipath_pcirev = rev;
+       dd->ipath_pcirev = pdev->revision;
 
 #if defined(__powerpc__)
        /* There isn't a generic way to specify writethrough mappings */
@@ -511,6 +521,9 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
        ipath_diag_add(dd);
        ipath_register_ib_device(dd);
 
+       /* Check that card status in STATUS_TIMEOUT seconds. */
+       schedule_delayed_work(&dd->status_work, HZ * STATUS_TIMEOUT);
+
        goto bail;
 
 bail_irqsetup:
@@ -638,6 +651,9 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev)
         */
        ipath_shutdown_device(dd);
 
+       cancel_delayed_work(&dd->status_work);
+       flush_scheduled_work();
+
        if (dd->verbs_dev)
                ipath_unregister_ib_device(dd->verbs_dev);
 
@@ -706,9 +722,9 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
        u64 sendctrl, sendorig;
 
        ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first);
-       sendorig = dd->ipath_sendctrl | INFINIPATH_S_DISARM;
+       sendorig = dd->ipath_sendctrl;
        for (i = first; i < last; i++) {
-               sendctrl = sendorig |
+               sendctrl = sendorig  | INFINIPATH_S_DISARM |
                        (i << INFINIPATH_S_DISARMPIOBUF_SHIFT);
                ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
                                 sendctrl);
@@ -719,12 +735,12 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
         * while we were looping; no critical bits that would require
         * locking.
         *
-        * Write a 0, and then the original value, reading scratch in
+        * disable PIOAVAILUPD, then re-enable, reading scratch in
         * between.  This seems to avoid a chip timing race that causes
         * pioavail updates to memory to stop.
         */
        ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-                        0);
+                        sendorig & ~IPATH_S_PIOBUFAVAILUPD);
        sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
        ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
                         dd->ipath_sendctrl);
@@ -1021,14 +1037,10 @@ void ipath_kreceive(struct ipath_devdata *dd)
                goto bail;
        }
 
-       /* There is already a thread processing this queue. */
-       if (test_and_set_bit(0, &dd->ipath_rcv_pending))
-               goto bail;
-
        l = dd->ipath_port0head;
        hdrqtail = (u32) le64_to_cpu(*dd->ipath_hdrqtailptr);
        if (l == hdrqtail)
-               goto done;
+               goto bail;
 
 reloop:
        for (i = 0; l != hdrqtail; i++) {
@@ -1163,10 +1175,6 @@ reloop:
        ipath_stats.sps_avgpkts_call =
                ipath_stats.sps_port0pkts / ++totcalls;
 
-done:
-       clear_bit(0, &dd->ipath_rcv_pending);
-       smp_mb__after_clear_bit();
-
 bail:;
 }
 
@@ -1596,6 +1604,35 @@ int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd)
        return ret;
 }
 
+
+/*
+ * Flush all sends that might be in the ready to send state, as well as any
+ * that are in the process of being sent.   Used whenever we need to be
+ * sure the send side is idle.  Cleans up all buffer state by canceling
+ * all pio buffers, and issuing an abort, which cleans up anything in the
+ * launch fifo.  The cancel is superfluous on some chip versions, but
+ * it's safer to always do it.
+ * PIOAvail bits are updated by the chip as if normal send had happened.
+ */
+void ipath_cancel_sends(struct ipath_devdata *dd)
+{
+       ipath_dbg("Cancelling all in-progress send buffers\n");
+       dd->ipath_lastcancel = jiffies+HZ/2; /* skip armlaunch errs a bit */
+       /*
+        * the abort bit is auto-clearing.  We read scratch to be sure
+        * that cancels and the abort have taken effect in the chip.
+        */
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+               INFINIPATH_S_ABORT);
+       ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+       ipath_disarm_piobufs(dd, 0,
+               (unsigned)(dd->ipath_piobcnt2k + dd->ipath_piobcnt4k));
+
+       /* and again, be sure all have hit the chip */
+       ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+}
+
+
 static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
 {
        static const char *what[4] = {
@@ -1617,14 +1654,8 @@ static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
                           INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]);
        /* flush all queued sends when going to DOWN or INIT, to be sure that
         * they don't block MAD packets */
-       if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT) {
-               ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-                                INFINIPATH_S_ABORT);
-               ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf,
-                                   (unsigned)(dd->ipath_piobcnt2k +
-                                   dd->ipath_piobcnt4k) -
-                                   dd->ipath_lastport_piobuf);
-       }
+       if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT)
+               ipath_cancel_sends(dd);
 
        ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
                         dd->ipath_ibcctrl | which);
@@ -1846,6 +1877,87 @@ void ipath_write_kreg_port(const struct ipath_devdata *dd, ipath_kreg regno,
        ipath_write_kreg(dd, where, value);
 }
 
+/*
+ * Following deal with the "obviously simple" task of overriding the state
+ * of the LEDS, which normally indicate link physical and logical status.
+ * The complications arise in dealing with different hardware mappings
+ * and the board-dependent routine being called from interrupts.
+ * and then there's the requirement to _flash_ them.
+ */
+#define LED_OVER_FREQ_SHIFT 8
+#define LED_OVER_FREQ_MASK (0xFF<<LED_OVER_FREQ_SHIFT)
+/* Below is "non-zero" to force override, but both actual LEDs are off */
+#define LED_OVER_BOTH_OFF (8)
+
+void ipath_run_led_override(unsigned long opaque)
+{
+       struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
+       int timeoff;
+       int pidx;
+       u64 lstate, ltstate, val;
+
+       if (!(dd->ipath_flags & IPATH_INITTED))
+               return;
+
+       pidx = dd->ipath_led_override_phase++ & 1;
+       dd->ipath_led_override = dd->ipath_led_override_vals[pidx];
+       timeoff = dd->ipath_led_override_timeoff;
+
+       /*
+        * below potentially restores the LED values per current status,
+        * should also possibly setup the traffic-blink register,
+        * but leave that to per-chip functions.
+        */
+       val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+       ltstate = (val >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+                 INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+       lstate = (val >> INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+                INFINIPATH_IBCS_LINKSTATE_MASK;
+
+       dd->ipath_f_setextled(dd, lstate, ltstate);
+       mod_timer(&dd->ipath_led_override_timer, jiffies + timeoff);
+}
+
+void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val)
+{
+       int timeoff, freq;
+
+       if (!(dd->ipath_flags & IPATH_INITTED))
+               return;
+
+       /* First check if we are blinking. If not, use 1HZ polling */
+       timeoff = HZ;
+       freq = (val & LED_OVER_FREQ_MASK) >> LED_OVER_FREQ_SHIFT;
+
+       if (freq) {
+               /* For blink, set each phase from one nybble of val */
+               dd->ipath_led_override_vals[0] = val & 0xF;
+               dd->ipath_led_override_vals[1] = (val >> 4) & 0xF;
+               timeoff = (HZ << 4)/freq;
+       } else {
+               /* Non-blink set both phases the same. */
+               dd->ipath_led_override_vals[0] = val & 0xF;
+               dd->ipath_led_override_vals[1] = val & 0xF;
+       }
+       dd->ipath_led_override_timeoff = timeoff;
+
+       /*
+        * If the timer has not already been started, do so. Use a "quick"
+        * timeout so the function will be called soon, to look at our request.
+        */
+       if (atomic_inc_return(&dd->ipath_led_override_timer_active) == 1) {
+               /* Need to start timer */
+               init_timer(&dd->ipath_led_override_timer);
+               dd->ipath_led_override_timer.function =
+                                                ipath_run_led_override;
+               dd->ipath_led_override_timer.data = (unsigned long) dd;
+               dd->ipath_led_override_timer.expires = jiffies + 1;
+               add_timer(&dd->ipath_led_override_timer);
+       } else {
+               atomic_dec(&dd->ipath_led_override_timer_active);
+       }
+}
+
 /**
  * ipath_shutdown_device - shut down a device
  * @dd: the infinipath device
@@ -1886,17 +1998,9 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
         */
        udelay(5);
 
-       /*
-        * abort any armed or launched PIO buffers that didn't go. (self
-        * clearing).  Will cause any packet currently being transmitted to
-        * go out with an EBP, and may also cause a short packet error on
-        * the receiver.
-        */
-       ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-                        INFINIPATH_S_ABORT);
-
        ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
                            INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+       ipath_cancel_sends(dd);
 
        /* disable IBC */
        dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
@@ -1909,7 +2013,6 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
         * Turn the LEDs off explictly for the same reason.
         */
        dd->ipath_f_quiet_serdes(dd);
-       dd->ipath_f_setextled(dd, 0, 0);
 
        if (dd->ipath_stats_timer_active) {
                del_timer_sync(&dd->ipath_stats_timer);
@@ -1925,6 +2028,9 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
                         ~0ULL & ~INFINIPATH_HWE_MEMBISTFAILED);
        ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL);
        ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL);
+
+       ipath_cdbg(VERBOSE, "Flush time and errors to EEPROM\n");
+       ipath_update_eeprom_log(dd);
 }
 
 /**
@@ -2085,6 +2191,16 @@ int ipath_reset_device(int unit)
                goto bail;
        }
 
+       if (atomic_read(&dd->ipath_led_override_timer_active)) {
+               /* Need to stop LED timer, _then_ shut off LEDs */
+               del_timer_sync(&dd->ipath_led_override_timer);
+               atomic_set(&dd->ipath_led_override_timer_active, 0);
+       }
+
+       /* Shut off LEDs after we are sure timer is not running */
+       dd->ipath_led_override = LED_OVER_BOTH_OFF;
+       dd->ipath_f_setextled(dd, 0, 0);
+
        dev_info(&dd->pcidev->dev, "Reset on unit %u requested\n", unit);
 
        if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) {
index 030185f90ee2b6ffe9ef70de2dc61ed4aa9c1c65..6b9147964a4f734638e42ae648493326b953d4b8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -95,39 +95,37 @@ static int i2c_gpio_set(struct ipath_devdata *dd,
                        enum i2c_type line,
                        enum i2c_state new_line_state)
 {
-       u64 read_val, write_val, mask, *gpioval;
+       u64 out_mask, dir_mask, *gpioval;
+       unsigned long flags = 0;
 
        gpioval = &dd->ipath_gpio_out;
-       read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
-       if (line == i2c_line_scl)
-               mask = dd->ipath_gpio_scl;
-       else
-               mask = dd->ipath_gpio_sda;
 
-       if (new_line_state == i2c_line_high)
+       if (line == i2c_line_scl) {
+               dir_mask = dd->ipath_gpio_scl;
+               out_mask = (1UL << dd->ipath_gpio_scl_num);
+       } else {
+               dir_mask = dd->ipath_gpio_sda;
+               out_mask = (1UL << dd->ipath_gpio_sda_num);
+       }
+
+       spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
+       if (new_line_state == i2c_line_high) {
                /* tri-state the output rather than force high */
-               write_val = read_val & ~mask;
-       else
+               dd->ipath_extctrl &= ~dir_mask;
+       } else {
                /* config line to be an output */
-               write_val = read_val | mask;
-       ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
+               dd->ipath_extctrl |= dir_mask;
+       }
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, dd->ipath_extctrl);
 
-       /* set high and verify */
+       /* set output as well (no real verify) */
        if (new_line_state == i2c_line_high)
-               write_val = 0x1UL;
+               *gpioval |= out_mask;
        else
-               write_val = 0x0UL;
+               *gpioval &= ~out_mask;
 
-       if (line == i2c_line_scl) {
-               write_val <<= dd->ipath_gpio_scl_num;
-               *gpioval = *gpioval & ~(1UL << dd->ipath_gpio_scl_num);
-               *gpioval |= write_val;
-       } else {
-               write_val <<= dd->ipath_gpio_sda_num;
-               *gpioval = *gpioval & ~(1UL << dd->ipath_gpio_sda_num);
-               *gpioval |= write_val;
-       }
        ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_out, *gpioval);
+       spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
 
        return 0;
 }
@@ -145,8 +143,9 @@ static int i2c_gpio_get(struct ipath_devdata *dd,
                        enum i2c_type line,
                        enum i2c_state *curr_statep)
 {
-       u64 read_val, write_val, mask;
+       u64 read_val, mask;
        int ret;
+       unsigned long flags = 0;
 
        /* check args */
        if (curr_statep == NULL) {
@@ -154,15 +153,21 @@ static int i2c_gpio_get(struct ipath_devdata *dd,
                goto bail;
        }
 
-       read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
        /* config line to be an input */
        if (line == i2c_line_scl)
                mask = dd->ipath_gpio_scl;
        else
                mask = dd->ipath_gpio_sda;
-       write_val = read_val & ~mask;
-       ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
+
+       spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
+       dd->ipath_extctrl &= ~mask;
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, dd->ipath_extctrl);
+       /*
+        * Below is very unlikely to reflect true input state if Output
+        * Enable actually changed.
+        */
        read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+       spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
 
        if (read_val & mask)
                *curr_statep = i2c_line_high;
@@ -192,6 +197,7 @@ static void i2c_wait_for_writes(struct ipath_devdata *dd)
 
 static void scl_out(struct ipath_devdata *dd, u8 bit)
 {
+       udelay(1);
        i2c_gpio_set(dd, i2c_line_scl, bit ? i2c_line_high : i2c_line_low);
 
        i2c_wait_for_writes(dd);
@@ -314,12 +320,18 @@ static int eeprom_reset(struct ipath_devdata *dd)
        int clock_cycles_left = 9;
        u64 *gpioval = &dd->ipath_gpio_out;
        int ret;
+       unsigned long flags;
 
-       eeprom_init = 1;
+       spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
+       /* Make sure shadows are consistent */
+       dd->ipath_extctrl = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
        *gpioval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_out);
+       spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
+
        ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg "
                   "is %llx\n", (unsigned long long) *gpioval);
 
+       eeprom_init = 1;
        /*
         * This is to get the i2c into a known state, by first going low,
         * then tristate sda (and then tristate scl as first thing
@@ -355,8 +367,8 @@ bail:
  * @len: number of bytes to receive
  */
 
-int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
-                     void *buffer, int len)
+static int ipath_eeprom_internal_read(struct ipath_devdata *dd,
+                                       u8 eeprom_offset, void *buffer, int len)
 {
        /* compiler complains unless initialized */
        u8 single_byte = 0;
@@ -406,6 +418,7 @@ bail:
        return ret;
 }
 
+
 /**
  * ipath_eeprom_write - writes data to the eeprom via I2C
  * @dd: the infinipath device
@@ -413,8 +426,8 @@ bail:
  * @buffer: data to write
  * @len: number of bytes to write
  */
-int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
-                      const void *buffer, int len)
+int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offset,
+                               const void *buffer, int len)
 {
        u8 single_byte;
        int sub_len;
@@ -488,6 +501,38 @@ bail:
        return ret;
 }
 
+/*
+ * The public entry-points ipath_eeprom_read() and ipath_eeprom_write()
+ * are now just wrappers around the internal functions.
+ */
+int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
+                       void *buff, int len)
+{
+       int ret;
+
+       ret = down_interruptible(&dd->ipath_eep_sem);
+       if (!ret) {
+               ret = ipath_eeprom_internal_read(dd, eeprom_offset, buff, len);
+               up(&dd->ipath_eep_sem);
+       }
+
+       return ret;
+}
+
+int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
+                       const void *buff, int len)
+{
+       int ret;
+
+       ret = down_interruptible(&dd->ipath_eep_sem);
+       if (!ret) {
+               ret = ipath_eeprom_internal_write(dd, eeprom_offset, buff, len);
+               up(&dd->ipath_eep_sem);
+       }
+
+       return ret;
+}
+
 static u8 flash_csum(struct ipath_flash *ifp, int adjust)
 {
        u8 *ip = (u8 *) ifp;
@@ -515,7 +560,7 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
        void *buf;
        struct ipath_flash *ifp;
        __be64 guid;
-       int len;
+       int len, eep_stat;
        u8 csum, *bguid;
        int t = dd->ipath_unit;
        struct ipath_devdata *dd0 = ipath_lookup(0);
@@ -559,7 +604,11 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
                goto bail;
        }
 
-       if (ipath_eeprom_read(dd, 0, buf, len)) {
+       down(&dd->ipath_eep_sem);
+       eep_stat = ipath_eeprom_internal_read(dd, 0, buf, len);
+       up(&dd->ipath_eep_sem);
+
+       if (eep_stat) {
                ipath_dev_err(dd, "Failed reading GUID from eeprom\n");
                goto done;
        }
@@ -634,8 +683,192 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
        ipath_cdbg(VERBOSE, "Initted GUID to %llx from eeprom\n",
                   (unsigned long long) be64_to_cpu(dd->ipath_guid));
 
+       memcpy(&dd->ipath_eep_st_errs, &ifp->if_errcntp, IPATH_EEP_LOG_CNT);
+       /*
+        * Power-on (actually "active") hours are kept as little-endian value
+        * in EEPROM, but as seconds in a (possibly as small as 24-bit)
+        * atomic_t while running.
+        */
+       atomic_set(&dd->ipath_active_time, 0);
+       dd->ipath_eep_hrs = ifp->if_powerhour[0] | (ifp->if_powerhour[1] << 8);
+
 done:
        vfree(buf);
 
 bail:;
 }
+
+/**
+ * ipath_update_eeprom_log - copy active-time and error counters to eeprom
+ * @dd: the infinipath device
+ *
+ * Although the time is kept as seconds in the ipath_devdata struct, it is
+ * rounded to hours for re-write, as we have only 16 bits in EEPROM.
+ * First-cut code reads whole (expected) struct ipath_flash, modifies,
+ * re-writes. Future direction: read/write only what we need, assuming
+ * that the EEPROM had to have been "good enough" for driver init, and
+ * if not, we aren't making it worse.
+ *
+ */
+
+int ipath_update_eeprom_log(struct ipath_devdata *dd)
+{
+       void *buf;
+       struct ipath_flash *ifp;
+       int len, hi_water;
+       uint32_t new_time, new_hrs;
+       u8 csum;
+       int ret, idx;
+       unsigned long flags;
+
+       /* first, check if we actually need to do anything. */
+       ret = 0;
+       for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
+               if (dd->ipath_eep_st_new_errs[idx]) {
+                       ret = 1;
+                       break;
+               }
+       }
+       new_time = atomic_read(&dd->ipath_active_time);
+
+       if (ret == 0 && new_time < 3600)
+               return 0;
+
+       /*
+        * The quick-check above determined that there is something worthy
+        * of logging, so get current contents and do a more detailed idea.
+        */
+       len = offsetof(struct ipath_flash, if_future);
+       buf = vmalloc(len);
+       ret = 1;
+       if (!buf) {
+               ipath_dev_err(dd, "Couldn't allocate memory to read %u "
+                               "bytes from eeprom for logging\n", len);
+               goto bail;
+       }
+
+       /* Grab semaphore and read current EEPROM. If we get an
+        * error, let go, but if not, keep it until we finish write.
+        */
+       ret = down_interruptible(&dd->ipath_eep_sem);
+       if (ret) {
+               ipath_dev_err(dd, "Unable to acquire EEPROM for logging\n");
+               goto free_bail;
+       }
+       ret = ipath_eeprom_internal_read(dd, 0, buf, len);
+       if (ret) {
+               up(&dd->ipath_eep_sem);
+               ipath_dev_err(dd, "Unable read EEPROM for logging\n");
+               goto free_bail;
+       }
+       ifp = (struct ipath_flash *)buf;
+
+       csum = flash_csum(ifp, 0);
+       if (csum != ifp->if_csum) {
+               up(&dd->ipath_eep_sem);
+               ipath_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n",
+                               csum, ifp->if_csum);
+               ret = 1;
+               goto free_bail;
+       }
+       hi_water = 0;
+       spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+       for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
+               int new_val = dd->ipath_eep_st_new_errs[idx];
+               if (new_val) {
+                       /*
+                        * If we have seen any errors, add to EEPROM values
+                        * We need to saturate at 0xFF (255) and we also
+                        * would need to adjust the checksum if we were
+                        * trying to minimize EEPROM traffic
+                        * Note that we add to actual current count in EEPROM,
+                        * in case it was altered while we were running.
+                        */
+                       new_val += ifp->if_errcntp[idx];
+                       if (new_val > 0xFF)
+                               new_val = 0xFF;
+                       if (ifp->if_errcntp[idx] != new_val) {
+                               ifp->if_errcntp[idx] = new_val;
+                               hi_water = offsetof(struct ipath_flash,
+                                               if_errcntp) + idx;
+                       }
+                       /*
+                        * update our shadow (used to minimize EEPROM
+                        * traffic), to match what we are about to write.
+                        */
+                       dd->ipath_eep_st_errs[idx] = new_val;
+                       dd->ipath_eep_st_new_errs[idx] = 0;
+               }
+       }
+       /*
+        * now update active-time. We would like to round to the nearest hour
+        * but unless atomic_t are sure to be proper signed ints we cannot,
+        * because we need to account for what we "transfer" to EEPROM and
+        * if we log an hour at 31 minutes, then we would need to set
+        * active_time to -29 to accurately count the _next_ hour.
+        */
+       if (new_time > 3600) {
+               new_hrs = new_time / 3600;
+               atomic_sub((new_hrs * 3600), &dd->ipath_active_time);
+               new_hrs += dd->ipath_eep_hrs;
+               if (new_hrs > 0xFFFF)
+                       new_hrs = 0xFFFF;
+               dd->ipath_eep_hrs = new_hrs;
+               if ((new_hrs & 0xFF) != ifp->if_powerhour[0]) {
+                       ifp->if_powerhour[0] = new_hrs & 0xFF;
+                       hi_water = offsetof(struct ipath_flash, if_powerhour);
+               }
+               if ((new_hrs >> 8) != ifp->if_powerhour[1]) {
+                       ifp->if_powerhour[1] = new_hrs >> 8;
+                       hi_water = offsetof(struct ipath_flash, if_powerhour)
+                                       + 1;
+               }
+       }
+       /*
+        * There is a tiny possibility that we could somehow fail to write
+        * the EEPROM after updating our shadows, but problems from holding
+        * the spinlock too long are a much bigger issue.
+        */
+       spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
+       if (hi_water) {
+               /* we made some change to the data, uopdate cksum and write */
+               csum = flash_csum(ifp, 1);
+               ret = ipath_eeprom_internal_write(dd, 0, buf, hi_water + 1);
+       }
+       up(&dd->ipath_eep_sem);
+       if (ret)
+               ipath_dev_err(dd, "Failed updating EEPROM\n");
+
+free_bail:
+       vfree(buf);
+bail:
+       return ret;
+
+}
+
+/**
+ * ipath_inc_eeprom_err - increment one of the four error counters
+ * that are logged to EEPROM.
+ * @dd: the infinipath device
+ * @eidx: 0..3, the counter to increment
+ * @incr: how much to add
+ *
+ * Each counter is 8-bits, and saturates at 255 (0xFF). They
+ * are copied to the EEPROM (aka flash) whenever ipath_update_eeprom_log()
+ * is called, but it can only be called in a context that allows sleep.
+ * This function can be called even at interrupt level.
+ */
+
+void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr)
+{
+       uint new_val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+       new_val = dd->ipath_eep_st_new_errs[eidx] + incr;
+       if (new_val > 255)
+               new_val = 255;
+       dd->ipath_eep_st_new_errs[eidx] = new_val;
+       spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
+       return;
+}
index 1272aaf2a78543f86fa9288e7cf85e2426ead2be..33ab0d6b80ff3085a0ed423b4fe980fd1c938807 100644 (file)
@@ -396,7 +396,8 @@ static int ipath_tid_update(struct ipath_portdata *pd, struct file *fp,
                           "TID %u, vaddr %lx, physaddr %llx pgp %p\n",
                           tid, vaddr, (unsigned long long) physaddr,
                           pagep[i]);
-               dd->ipath_f_put_tid(dd, &tidbase[tid], 1, physaddr);
+               dd->ipath_f_put_tid(dd, &tidbase[tid], RCVHQ_RCV_TYPE_EXPECTED,
+                                   physaddr);
                /*
                 * don't check this tid in ipath_portshadow, since we
                 * just filled it in; start with the next one.
@@ -422,7 +423,8 @@ static int ipath_tid_update(struct ipath_portdata *pd, struct file *fp,
                        if (dd->ipath_pageshadow[porttid + tid]) {
                                ipath_cdbg(VERBOSE, "Freeing TID %u\n",
                                           tid);
-                               dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
+                               dd->ipath_f_put_tid(dd, &tidbase[tid],
+                                                   RCVHQ_RCV_TYPE_EXPECTED,
                                                    dd->ipath_tidinvalid);
                                pci_unmap_page(dd->pcidev,
                                        dd->ipath_physshadow[porttid + tid],
@@ -538,7 +540,8 @@ static int ipath_tid_free(struct ipath_portdata *pd, unsigned subport,
                if (dd->ipath_pageshadow[porttid + tid]) {
                        ipath_cdbg(VERBOSE, "PID %u freeing TID %u\n",
                                   pd->port_pid, tid);
-                       dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
+                       dd->ipath_f_put_tid(dd, &tidbase[tid],
+                                           RCVHQ_RCV_TYPE_EXPECTED,
                                            dd->ipath_tidinvalid);
                        pci_unmap_page(dd->pcidev,
                                dd->ipath_physshadow[porttid + tid],
@@ -921,7 +924,8 @@ static int ipath_create_user_egr(struct ipath_portdata *pd)
                                            (u64 __iomem *)
                                            ((char __iomem *)
                                             dd->ipath_kregbase +
-                                            dd->ipath_rcvegrbase), 0, pa);
+                                            dd->ipath_rcvegrbase),
+                                           RCVHQ_RCV_TYPE_EAGER, pa);
                        pa += egrsize;
                }
                cond_resched(); /* don't hog the cpu */
@@ -1337,68 +1341,133 @@ bail:
        return ret;
 }
 
-static unsigned int ipath_poll(struct file *fp,
-                              struct poll_table_struct *pt)
+static unsigned int ipath_poll_urgent(struct ipath_portdata *pd,
+                                     struct file *fp,
+                                     struct poll_table_struct *pt)
 {
-       struct ipath_portdata *pd;
-       u32 head, tail;
-       int bit;
        unsigned pollflag = 0;
        struct ipath_devdata *dd;
 
-       pd = port_fp(fp);
-       if (!pd)
-               goto bail;
        dd = pd->port_dd;
 
-       bit = pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT;
-       set_bit(bit, &dd->ipath_rcvctrl);
+       if (test_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag)) {
+               pollflag |= POLLERR;
+               clear_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag);
+       }
 
-       /*
-        * Before blocking, make sure that head is still == tail,
-        * reading from the chip, so we can be sure the interrupt
-        * enable has made it to the chip.  If not equal, disable
-        * interrupt again and return immediately.  This avoids races,
-        * and the overhead of the chip read doesn't matter much at
-        * this point, since we are waiting for something anyway.
-        */
+       if (test_bit(IPATH_PORT_WAITING_URG, &pd->int_flag)) {
+               pollflag |= POLLIN | POLLRDNORM;
+               clear_bit(IPATH_PORT_WAITING_URG, &pd->int_flag);
+       }
 
-       ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
-                        dd->ipath_rcvctrl);
+       if (!pollflag) {
+               set_bit(IPATH_PORT_WAITING_URG, &pd->port_flag);
+               if (pd->poll_type & IPATH_POLL_TYPE_OVERFLOW)
+                       set_bit(IPATH_PORT_WAITING_OVERFLOW,
+                               &pd->port_flag);
+
+               poll_wait(fp, &pd->port_wait, pt);
+       }
+
+       return pollflag;
+}
+
+static unsigned int ipath_poll_next(struct ipath_portdata *pd,
+                                   struct file *fp,
+                                   struct poll_table_struct *pt)
+{
+       u32 head, tail;
+       unsigned pollflag = 0;
+       struct ipath_devdata *dd;
+
+       dd = pd->port_dd;
 
        head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port);
-       tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+       tail = *(volatile u64 *)pd->port_rcvhdrtail_kvaddr;
 
-       if (tail == head) {
+       if (test_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag)) {
+               pollflag |= POLLERR;
+               clear_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag);
+       }
+
+       if (tail != head ||
+           test_bit(IPATH_PORT_WAITING_RCV, &pd->int_flag)) {
+               pollflag |= POLLIN | POLLRDNORM;
+               clear_bit(IPATH_PORT_WAITING_RCV, &pd->int_flag);
+       }
+
+       if (!pollflag) {
                set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
+               if (pd->poll_type & IPATH_POLL_TYPE_OVERFLOW)
+                       set_bit(IPATH_PORT_WAITING_OVERFLOW,
+                               &pd->port_flag);
+
+               set_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT,
+                       &dd->ipath_rcvctrl);
+
+               ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+                                dd->ipath_rcvctrl);
+
                if (dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */
-                       (void)ipath_write_ureg(dd, ur_rcvhdrhead,
-                                              dd->ipath_rhdrhead_intr_off
-                                              | head, pd->port_port);
-               poll_wait(fp, &pd->port_wait, pt);
+                       ipath_write_ureg(dd, ur_rcvhdrhead,
+                                        dd->ipath_rhdrhead_intr_off | head,
+                                        pd->port_port);
 
-               if (test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) {
-                       /* timed out, no packets received */
-                       clear_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
-                       pd->port_rcvwait_to++;
-               }
-               else
-                       pollflag = POLLIN | POLLRDNORM;
-       }
-       else {
-               /* it's already happened; don't do wait_event overhead */
-               pollflag = POLLIN | POLLRDNORM;
-               pd->port_rcvnowait++;
+               poll_wait(fp, &pd->port_wait, pt);
        }
 
-       clear_bit(bit, &dd->ipath_rcvctrl);
-       ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
-                        dd->ipath_rcvctrl);
+       return pollflag;
+}
+
+static unsigned int ipath_poll(struct file *fp,
+                              struct poll_table_struct *pt)
+{
+       struct ipath_portdata *pd;
+       unsigned pollflag;
+
+       pd = port_fp(fp);
+       if (!pd)
+               pollflag = 0;
+       else if (pd->poll_type & IPATH_POLL_TYPE_URGENT)
+               pollflag = ipath_poll_urgent(pd, fp, pt);
+       else
+               pollflag = ipath_poll_next(pd, fp, pt);
 
-bail:
        return pollflag;
 }
 
+static int ipath_supports_subports(int user_swmajor, int user_swminor)
+{
+       /* no subport implementation prior to software version 1.3 */
+       return (user_swmajor > 1) || (user_swminor >= 3);
+}
+
+static int ipath_compatible_subports(int user_swmajor, int user_swminor)
+{
+       /* this code is written long-hand for clarity */
+       if (IPATH_USER_SWMAJOR != user_swmajor) {
+               /* no promise of compatibility if major mismatch */
+               return 0;
+       }
+       if (IPATH_USER_SWMAJOR == 1) {
+               switch (IPATH_USER_SWMINOR) {
+               case 0:
+               case 1:
+               case 2:
+                       /* no subport implementation so cannot be compatible */
+                       return 0;
+               case 3:
+                       /* 3 is only compatible with itself */
+                       return user_swminor == 3;
+               default:
+                       /* >= 4 are compatible (or are expected to be) */
+                       return user_swminor >= 4;
+               }
+       }
+       /* make no promises yet for future major versions */
+       return 0;
+}
+
 static int init_subports(struct ipath_devdata *dd,
                         struct ipath_portdata *pd,
                         const struct ipath_user_info *uinfo)
@@ -1408,20 +1477,32 @@ static int init_subports(struct ipath_devdata *dd,
        size_t size;
 
        /*
-        * If the user is requesting zero or one port,
+        * If the user is requesting zero subports,
         * skip the subport allocation.
         */
-       if (uinfo->spu_subport_cnt <= 1)
+       if (uinfo->spu_subport_cnt <= 0)
+               goto bail;
+
+       /* Self-consistency check for ipath_compatible_subports() */
+       if (ipath_supports_subports(IPATH_USER_SWMAJOR, IPATH_USER_SWMINOR) &&
+           !ipath_compatible_subports(IPATH_USER_SWMAJOR,
+                                      IPATH_USER_SWMINOR)) {
+               dev_info(&dd->pcidev->dev,
+                        "Inconsistent ipath_compatible_subports()\n");
                goto bail;
+       }
 
-       /* Old user binaries don't know about new subport implementation */
-       if ((uinfo->spu_userversion & 0xffff) != IPATH_USER_SWMINOR) {
+       /* Check for subport compatibility */
+       if (!ipath_compatible_subports(uinfo->spu_userversion >> 16,
+                                      uinfo->spu_userversion & 0xffff)) {
                dev_info(&dd->pcidev->dev,
-                        "Mismatched user minor version (%d) and driver "
-                         "minor version (%d) while port sharing. Ensure "
+                        "Mismatched user version (%d.%d) and driver "
+                        "version (%d.%d) while port sharing. Ensure "
                          "that driver and library are from the same "
                          "release.\n",
+                        (int) (uinfo->spu_userversion >> 16),
                          (int) (uinfo->spu_userversion & 0xffff),
+                        IPATH_USER_SWMAJOR,
                         IPATH_USER_SWMINOR);
                goto bail;
        }
@@ -1725,14 +1806,13 @@ static int ipath_open(struct inode *in, struct file *fp)
        return fp->private_data ? 0 : -ENOMEM;
 }
 
-
 /* Get port early, so can set affinity prior to memory allocation */
 static int ipath_assign_port(struct file *fp,
                              const struct ipath_user_info *uinfo)
 {
        int ret;
        int i_minor;
-       unsigned swminor;
+       unsigned swmajor, swminor;
 
        /* Check to be sure we haven't already initialized this file */
        if (port_fp(fp)) {
@@ -1741,7 +1821,8 @@ static int ipath_assign_port(struct file *fp,
        }
 
        /* for now, if major version is different, bail */
-       if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) {
+       swmajor = uinfo->spu_userversion >> 16;
+       if (swmajor != IPATH_USER_SWMAJOR) {
                ipath_dbg("User major version %d not same as driver "
                          "major %d\n", uinfo->spu_userversion >> 16,
                          IPATH_USER_SWMAJOR);
@@ -1756,7 +1837,8 @@ static int ipath_assign_port(struct file *fp,
 
        mutex_lock(&ipath_mutex);
 
-       if (swminor == IPATH_USER_SWMINOR && uinfo->spu_subport_cnt &&
+       if (ipath_compatible_subports(swmajor, swminor) &&
+           uinfo->spu_subport_cnt &&
            (ret = find_shared_port(fp, uinfo))) {
                mutex_unlock(&ipath_mutex);
                if (ret > 0)
@@ -2020,7 +2102,8 @@ static int ipath_port_info(struct ipath_portdata *pd, u16 subport,
        info.port = pd->port_port;
        info.subport = subport;
        /* Don't return new fields if old library opened the port. */
-       if ((pd->userversion & 0xffff) == IPATH_USER_SWMINOR) {
+       if (ipath_supports_subports(pd->userversion >> 16,
+                                   pd->userversion & 0xffff)) {
                /* Number of user ports available for this device. */
                info.num_ports = pd->port_dd->ipath_cfgports - 1;
                info.num_subports = pd->port_subport_cnt;
@@ -2123,6 +2206,11 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
                src = NULL;
                dest = NULL;
                break;
+       case IPATH_CMD_POLL_TYPE:
+               copy = sizeof(cmd.cmd.poll_type);
+               dest = &cmd.cmd.poll_type;
+               src = &ucmd->cmd.poll_type;
+               break;
        default:
                ret = -EINVAL;
                goto bail;
@@ -2195,6 +2283,9 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
        case IPATH_CMD_PIOAVAILUPD:
                ret = ipath_force_pio_avail_update(pd->port_dd);
                break;
+       case IPATH_CMD_POLL_TYPE:
+               pd->poll_type = cmd.cmd.poll_type;
+               break;
        }
 
        if (ret >= 0)
index ebd5c7bd2cdbec4680163237360ee88b12822b67..2e689b974e1f48ed4e6538b72882e166b60c36ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -257,9 +257,14 @@ static ssize_t atomic_port_info_read(struct file *file, char __user *buf,
                /* Notimpl InitType (actually, an SMA decision) */
                /* VLHighLimit is 0 (only one VL) */
                ; /* VLArbitrationHighCap is 0 (only one VL) */
+       /*
+        * Note: the chips support a maximum MTU of 4096, but the driver
+        * hasn't implemented this feature yet, so set the maximum
+        * to 2048.
+        */
        portinfo[10] =  /* VLArbitrationLowCap is 0 (only one VL) */
                /* InitTypeReply is SMA decision */
-               (5 << 16)       /* MTUCap 4096 */
+               (4 << 16)       /* MTUCap 2048 */
                | (7 << 13)     /* VLStallCount */
                | (0x1f << 8)   /* HOQLife */
                | (1 << 4)
index 4171198fc2025cc6358c7ac21e0ddcfb13206e48..650745d83faccbe0f3da87ffbc6feb11087b1137 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -36,6 +36,7 @@
  * HT chip.
  */
 
+#include <linux/vmalloc.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/htirq.h>
@@ -439,6 +440,7 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
        u32 bits, ctrl;
        int isfatal = 0;
        char bitsmsg[64];
+       int log_idx;
 
        hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
 
@@ -467,6 +469,11 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
 
        hwerrs &= dd->ipath_hwerrmask;
 
+       /* We log some errors to EEPROM, check if we have any of those. */
+       for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx)
+               if (hwerrs & dd->ipath_eep_st_masks[log_idx].hwerrs_to_log)
+                       ipath_inc_eeprom_err(dd, log_idx, 1);
+
        /*
         * make sure we get this much out, unless told to be quiet,
         * it's a parity error we may recover from,
@@ -502,9 +509,7 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
                if (!hwerrs) {
                        ipath_dbg("Clearing freezemode on ignored or "
                                  "recovered hardware error\n");
-                       ctrl &= ~INFINIPATH_C_FREEZEMODE;
-                       ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
-                                        ctrl);
+                       ipath_clear_freeze(dd);
                }
        }
 
@@ -672,10 +677,16 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
        if (n)
                snprintf(name, namelen, "%s", n);
 
+       if (dd->ipath_boardrev != 6 && dd->ipath_boardrev != 7 &&
+           dd->ipath_boardrev != 11) {
+               ipath_dev_err(dd, "Unsupported InfiniPath board %s!\n", name);
+               ret = 1;
+               goto bail;
+       }
        if (dd->ipath_majrev != 3 || (dd->ipath_minrev < 2 ||
-               dd->ipath_minrev > 3)) {
+               dd->ipath_minrev > 4)) {
                /*
-                * This version of the driver only supports Rev 3.2 and 3.3
+                * This version of the driver only supports Rev 3.2 - 3.4
                 */
                ipath_dev_err(dd,
                              "Unsupported InfiniPath hardware revision %u.%u!\n",
@@ -689,36 +700,11 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
         * copies
         */
        dd->ipath_flags |= IPATH_32BITCOUNTERS;
+       dd->ipath_flags |= IPATH_GPIO_INTR;
        if (dd->ipath_htspeed != 800)
                ipath_dev_err(dd,
                              "Incorrectly configured for HT @ %uMHz\n",
                              dd->ipath_htspeed);
-       if (dd->ipath_boardrev == 7 || dd->ipath_boardrev == 11 ||
-           dd->ipath_boardrev == 6)
-               dd->ipath_flags |= IPATH_GPIO_INTR;
-       else
-               dd->ipath_flags |= IPATH_POLL_RX_INTR;
-       if (dd->ipath_boardrev == 8) {  /* LS/X-1 */
-               u64 val;
-               val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
-               if (val & INFINIPATH_EXTS_SERDESSEL) {
-                       /*
-                        * hardware disabled
-                        *
-                        * This means that the chip is hardware disabled,
-                        * and will not be able to bring up the link,
-                        * in any case.  We special case this and abort
-                        * early, to avoid later messages.  We also set
-                        * the DISABLED status bit
-                        */
-                       ipath_dbg("Unit %u is hardware-disabled\n",
-                                 dd->ipath_unit);
-                       *dd->ipath_statusp |= IPATH_STATUS_DISABLED;
-                       /* this value is handled differently */
-                       ret = 2;
-                       goto bail;
-               }
-       }
        ret = 0;
 
 bail:
@@ -1058,12 +1044,24 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
                                     u64 lst, u64 ltst)
 {
        u64 extctl;
+       unsigned long flags = 0;
 
        /* the diags use the LED to indicate diag info, so we leave
         * the external LED alone when the diags are running */
        if (ipath_diag_inuse)
                return;
 
+       /* Allow override of LED display for, e.g. Locating system in rack */
+       if (dd->ipath_led_override) {
+               ltst = (dd->ipath_led_override & IPATH_LED_PHYS)
+                       ? INFINIPATH_IBCS_LT_STATE_LINKUP
+                       : INFINIPATH_IBCS_LT_STATE_DISABLED;
+               lst = (dd->ipath_led_override & IPATH_LED_LOG)
+                       ? INFINIPATH_IBCS_L_STATE_ACTIVE
+                       : INFINIPATH_IBCS_L_STATE_DOWN;
+       }
+
+       spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
        /*
         * start by setting both LED control bits to off, then turn
         * on the appropriate bit(s).
@@ -1092,6 +1090,7 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
        }
        dd->ipath_extctrl = extctl;
        ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+       spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
 }
 
 static void ipath_init_ht_variables(struct ipath_devdata *dd)
@@ -1157,6 +1156,22 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd)
 
        dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
        dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+
+       /*
+        * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
+        * 2 is Some Misc, 3 is reserved for future.
+        */
+       dd->ipath_eep_st_masks[0].hwerrs_to_log =
+               INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
+               INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT;
+
+       dd->ipath_eep_st_masks[1].hwerrs_to_log =
+               INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+               INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
+
+       dd->ipath_eep_st_masks[2].errs_to_log =
+               INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
+
 }
 
 /**
@@ -1372,7 +1387,7 @@ static void ipath_ht_quiet_serdes(struct ipath_devdata *dd)
  * ipath_pe_put_tid - write a TID in chip
  * @dd: the infinipath device
  * @tidptr: pointer to the expected TID (in chip) to udpate
- * @tidtype: 0 for eager, 1 for expected
+ * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected
  * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
  *
  * This exists as a separate routine to allow for special locking etc.
@@ -1393,7 +1408,7 @@ static void ipath_ht_put_tid(struct ipath_devdata *dd,
                                 "40 bits, using only 40!!!\n", pa);
                        pa &= INFINIPATH_RT_ADDR_MASK;
                }
-               if (type == 0)
+               if (type == RCVHQ_RCV_TYPE_EAGER)
                        pa |= dd->ipath_tidtemplate;
                else {
                        /* in words (fixed, full page).  */
@@ -1433,7 +1448,8 @@ static void ipath_ht_clear_tids(struct ipath_devdata *dd, unsigned port)
                                   port * dd->ipath_rcvtidcnt *
                                   sizeof(*tidbase));
        for (i = 0; i < dd->ipath_rcvtidcnt; i++)
-               ipath_ht_put_tid(dd, &tidbase[i], 1, dd->ipath_tidinvalid);
+               ipath_ht_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED,
+                                dd->ipath_tidinvalid);
 
        tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
                                   dd->ipath_rcvegrbase +
@@ -1441,7 +1457,8 @@ static void ipath_ht_clear_tids(struct ipath_devdata *dd, unsigned port)
                                   sizeof(*tidbase));
 
        for (i = 0; i < dd->ipath_rcvegrcnt; i++)
-               ipath_ht_put_tid(dd, &tidbase[i], 0, dd->ipath_tidinvalid);
+               ipath_ht_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EAGER,
+                                dd->ipath_tidinvalid);
 }
 
 /**
@@ -1528,11 +1545,6 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
                writel(16, piobuf);
                piobuf += pioincr;
        }
-       /*
-        * self-clearing
-        */
-       ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-                        INFINIPATH_S_ABORT);
 
        ipath_get_eeprom_info(dd);
        if (dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' &&
@@ -1543,8 +1555,10 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
                 * with 128, rather than 112.
                 */
                dd->ipath_flags |= IPATH_GPIO_INTR;
-               dd->ipath_flags &= ~IPATH_POLL_RX_INTR;
-       }
+       } else
+               ipath_dev_err(dd, "Unsupported InfiniPath serial "
+                             "number %.16s!\n", dd->ipath_serial);
+
        return 0;
 }
 
@@ -1561,7 +1575,6 @@ static int ipath_ht_txe_recover(struct ipath_devdata *dd)
        }
        dev_info(&dd->pcidev->dev,
                "Recovering from TXE PIO parity error\n");
-       ipath_disarm_senderrbufs(dd, 1);
        return 1;
 }
 
index 4e2e3dfeb2c8c3f77cb245ee91c2bbeeff470380..9868ccda5f26769b66dc76593ef107a53a5630f2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -296,13 +296,6 @@ static const struct ipath_cregs ipath_pe_cregs = {
 #define IPATH_GPIO_SCL (1ULL << \
        (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
 
-/*
- * Rev2 silicon allows suppressing check for ArmLaunch errors.
- * this can speed up short packet sends on systems that do
- * not guaranteee write-order.
- */
-#define INFINIPATH_XGXS_SUPPRESS_ARMLAUNCH_ERR (1ULL<<63)
-
 /* 6120 specific hardware errors... */
 static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
        INFINIPATH_HWE_MSG(PCIEPOISONEDTLP, "PCIe Poisoned TLP"),
@@ -347,6 +340,7 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
        u32 bits, ctrl;
        int isfatal = 0;
        char bitsmsg[64];
+       int log_idx;
 
        hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
        if (!hwerrs) {
@@ -374,6 +368,11 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
 
        hwerrs &= dd->ipath_hwerrmask;
 
+       /* We log some errors to EEPROM, check if we have any of those. */
+       for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx)
+               if (hwerrs & dd->ipath_eep_st_masks[log_idx].hwerrs_to_log)
+                       ipath_inc_eeprom_err(dd, log_idx, 1);
+
        /*
         * make sure we get this much out, unless told to be quiet,
         * or it's occurred within the last 5 seconds
@@ -431,10 +430,12 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
                        *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
                        dd->ipath_flags &= ~IPATH_INITTED;
                } else {
-                       ipath_dbg("Clearing freezemode on ignored hardware "
-                                 "error\n");
-                       ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
-                                        dd->ipath_control);
+                       static u32 freeze_cnt;
+
+                       freeze_cnt++;
+                       ipath_dbg("Clearing freezemode on ignored or recovered "
+                                 "hardware error (%u)\n", freeze_cnt);
+                       ipath_clear_freeze(dd);
                }
        }
 
@@ -680,17 +681,6 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
                val |= dd->ipath_rx_pol_inv <<
                        INFINIPATH_XGXS_RX_POL_SHIFT;
        }
-       if (dd->ipath_minrev >= 2) {
-               /* Rev 2. can tolerate multiple writes to PBC, and
-                * allowing them can provide lower latency on some
-                * CPUs, but this feature is off by default, only
-                * turned on by setting D63 of XGXSconfig reg.
-                * May want to make this conditional more
-                * fine-grained in future. This is not exactly
-                * related to XGXS, but where the bit ended up.
-                */
-               val |= INFINIPATH_XGXS_SUPPRESS_ARMLAUNCH_ERR;
-       }
        if (val != prev_val)
                ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
 
@@ -791,12 +781,24 @@ static void ipath_setup_pe_setextled(struct ipath_devdata *dd, u64 lst,
                                     u64 ltst)
 {
        u64 extctl;
+       unsigned long flags = 0;
 
        /* the diags use the LED to indicate diag info, so we leave
         * the external LED alone when the diags are running */
        if (ipath_diag_inuse)
                return;
 
+       /* Allow override of LED display for, e.g. Locating system in rack */
+       if (dd->ipath_led_override) {
+               ltst = (dd->ipath_led_override & IPATH_LED_PHYS)
+                       ? INFINIPATH_IBCS_LT_STATE_LINKUP
+                       : INFINIPATH_IBCS_LT_STATE_DISABLED;
+               lst = (dd->ipath_led_override & IPATH_LED_LOG)
+                       ? INFINIPATH_IBCS_L_STATE_ACTIVE
+                       : INFINIPATH_IBCS_L_STATE_DOWN;
+       }
+
+       spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
        extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
                                       INFINIPATH_EXTC_LED2PRIPORT_ON);
 
@@ -806,6 +808,7 @@ static void ipath_setup_pe_setextled(struct ipath_devdata *dd, u64 lst,
                extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
        dd->ipath_extctrl = extctl;
        ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+       spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
 }
 
 /**
@@ -955,6 +958,27 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
 
        dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
        dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+
+       /*
+        * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
+        * 2 is Some Misc, 3 is reserved for future.
+        */
+       dd->ipath_eep_st_masks[0].hwerrs_to_log =
+               INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
+               INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT;
+
+       /* Ignore errors in PIO/PBC on systems with unordered write-combining */
+       if (ipath_unordered_wc())
+               dd->ipath_eep_st_masks[0].hwerrs_to_log &= ~TXE_PIO_PARITY;
+
+       dd->ipath_eep_st_masks[1].hwerrs_to_log =
+               INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+               INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
+
+       dd->ipath_eep_st_masks[2].errs_to_log =
+               INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
+
+
 }
 
 /* setup the MSI stuff again after a reset.  I'd like to just call
@@ -1082,7 +1106,7 @@ bail:
  * ipath_pe_put_tid - write a TID in chip
  * @dd: the infinipath device
  * @tidptr: pointer to the expected TID (in chip) to udpate
- * @tidtype: 0 for eager, 1 for expected
+ * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected
  * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
  *
  * This exists as a separate routine to allow for special locking etc.
@@ -1108,7 +1132,7 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
                                      "BUG: Physical page address 0x%lx "
                                      "has bits set in 31-29\n", pa);
 
-               if (type == 0)
+               if (type == RCVHQ_RCV_TYPE_EAGER)
                        pa |= dd->ipath_tidtemplate;
                else /* for now, always full 4KB page */
                        pa |= 2 << 29;
@@ -1132,7 +1156,7 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
  * ipath_pe_put_tid_2 - write a TID in chip, Revision 2 or higher
  * @dd: the infinipath device
  * @tidptr: pointer to the expected TID (in chip) to udpate
- * @tidtype: 0 for eager, 1 for expected
+ * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected
  * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
  *
  * This exists as a separate routine to allow for selection of the
@@ -1157,7 +1181,7 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr,
                                      "BUG: Physical page address 0x%lx "
                                      "has bits set in 31-29\n", pa);
 
-               if (type == 0)
+               if (type == RCVHQ_RCV_TYPE_EAGER)
                        pa |= dd->ipath_tidtemplate;
                else /* for now, always full 4KB page */
                        pa |= 2 << 29;
@@ -1196,7 +1220,8 @@ static void ipath_pe_clear_tids(struct ipath_devdata *dd, unsigned port)
                 port * dd->ipath_rcvtidcnt * sizeof(*tidbase));
 
        for (i = 0; i < dd->ipath_rcvtidcnt; i++)
-               ipath_pe_put_tid(dd, &tidbase[i], 0, tidinv);
+               ipath_pe_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED,
+                                tidinv);
 
        tidbase = (u64 __iomem *)
                ((char __iomem *)(dd->ipath_kregbase) +
@@ -1204,7 +1229,8 @@ static void ipath_pe_clear_tids(struct ipath_devdata *dd, unsigned port)
                 port * dd->ipath_rcvegrcnt * sizeof(*tidbase));
 
        for (i = 0; i < dd->ipath_rcvegrcnt; i++)
-               ipath_pe_put_tid(dd, &tidbase[i], 1, tidinv);
+               ipath_pe_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EAGER,
+                                tidinv);
 }
 
 /**
@@ -1311,13 +1337,6 @@ static int ipath_pe_get_base_info(struct ipath_portdata *pd, void *kbase)
 
        dd = pd->port_dd;
 
-       if (dd != NULL && dd->ipath_minrev >= 2) {
-               ipath_cdbg(PROC, "IBA6120 Rev2, allow multiple PBC write\n");
-               kinfo->spi_runtime_flags |= IPATH_RUNTIME_PBC_REWRITE;
-               ipath_cdbg(PROC, "IBA6120 Rev2, allow loose DMA alignment\n");
-               kinfo->spi_runtime_flags |= IPATH_RUNTIME_LOOSE_DMA_ALIGN;
-       }
-
 done:
        kinfo->spi_runtime_flags |= IPATH_RUNTIME_PCIE;
        return 0;
@@ -1354,7 +1373,6 @@ static int ipath_pe_txe_recover(struct ipath_devdata *dd)
                dev_info(&dd->pcidev->dev,
                        "Recovering from TXE PIO parity error\n");
        }
-       ipath_disarm_senderrbufs(dd, 1);
        return 1;
 }
 
index 7045ba6894944dd3f1a593661ef083b74069bb6d..49951d5838049349df8ca39237365deb90525fbd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -133,7 +133,8 @@ static int create_port0_egr(struct ipath_devdata *dd)
                                   dd->ipath_ibmaxlen, PCI_DMA_FROMDEVICE);
                dd->ipath_f_put_tid(dd, e + (u64 __iomem *)
                                    ((char __iomem *) dd->ipath_kregbase +
-                                    dd->ipath_rcvegrbase), 0,
+                                    dd->ipath_rcvegrbase),
+                                   RCVHQ_RCV_TYPE_EAGER,
                                    dd->ipath_port0_skbinfo[e].phys);
        }
 
@@ -310,7 +311,12 @@ static int init_chip_first(struct ipath_devdata *dd,
        val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiosize);
        dd->ipath_piosize2k = val & ~0U;
        dd->ipath_piosize4k = val >> 32;
-       dd->ipath_ibmtu = 4096; /* default to largest legal MTU */
+       /*
+        * Note: the chips support a maximum MTU of 4096, but the driver
+        * hasn't implemented this feature yet, so set the initial value
+        * to 2048.
+        */
+       dd->ipath_ibmtu = 2048;
        val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufcnt);
        dd->ipath_piobcnt2k = val & ~0U;
        dd->ipath_piobcnt4k = val >> 32;
@@ -340,6 +346,10 @@ static int init_chip_first(struct ipath_devdata *dd,
 
        spin_lock_init(&dd->ipath_tid_lock);
 
+       spin_lock_init(&dd->ipath_gpio_lock);
+       spin_lock_init(&dd->ipath_eep_st_lock);
+       sema_init(&dd->ipath_eep_sem, 1);
+
 done:
        *pdp = pd;
        return ret;
@@ -646,7 +656,7 @@ static int init_housekeeping(struct ipath_devdata *dd,
        ret = dd->ipath_f_get_boardname(dd, boardn, sizeof boardn);
 
        snprintf(dd->ipath_boardversion, sizeof(dd->ipath_boardversion),
-                "Driver %u.%u, %s, InfiniPath%u %u.%u, PCI %u, "
+                "ChipABI %u.%u, %s, InfiniPath%u %u.%u, PCI %u, "
                 "SW Compat %u\n",
                 IPATH_CHIP_VERS_MAJ, IPATH_CHIP_VERS_MIN, boardn,
                 (unsigned)(dd->ipath_revision >> INFINIPATH_R_ARCH_SHIFT) &
@@ -727,7 +737,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
        uports = dd->ipath_cfgports ? dd->ipath_cfgports - 1 : 0;
        if (ipath_kpiobufs == 0) {
                /* not set by user (this is default) */
-               if (piobufs >= (uports * IPATH_MIN_USER_PORT_BUFCNT) + 32)
+               if (piobufs > 144)
                        kpiobufs = 32;
                else
                        kpiobufs = 16;
@@ -767,6 +777,12 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
                   piobufs, dd->ipath_pbufsport, uports);
 
        dd->ipath_f_early_init(dd);
+       /*
+        * cancel any possible active sends from early driver load.
+        * Follows early_init because some chips have to initialize
+        * PIO buffers in early_init to avoid false parity errors.
+        */
+       ipath_cancel_sends(dd);
 
        /* early_init sets rcvhdrentsize and rcvhdrsize, so this must be
         * done after early_init */
index a90d3b5699c46cc1169faf99ef3c72fbc4a92772..47aa43428fbf90b1284b6af4dee729debdc976bd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -93,7 +93,8 @@ void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
 
        if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {
                int i;
-               if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG)) {
+               if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG) &&
+                       dd->ipath_lastcancel > jiffies) {
                        __IPATH_DBG_WHICH(__IPATH_PKTDBG|__IPATH_DBG,
                                          "SendbufErrs %lx %lx", sbuf[0],
                                          sbuf[1]);
@@ -108,7 +109,8 @@ void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
                                        ipath_clrpiobuf(dd, i);
                                ipath_disarm_piobufs(dd, i, 1);
                        }
-               dd->ipath_lastcancel = jiffies+3; /* no armlaunch for a bit */
+               /* ignore armlaunch errs for a bit */
+               dd->ipath_lastcancel = jiffies+3;
        }
 }
 
@@ -130,6 +132,17 @@ void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
         INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SPKTLEN | \
         INFINIPATH_E_INVALIDADDR)
 
+/*
+ * this is similar to E_SUM_ERRS, but can't ignore armlaunch, don't ignore
+ * errors not related to freeze and cancelling buffers.  Can't ignore
+ * armlaunch because could get more while still cleaning up, and need
+ * to cancel those as they happen.
+ */
+#define E_SPKT_ERRS_IGNORE \
+        (INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \
+        INFINIPATH_E_SMAXPKTLEN | INFINIPATH_E_SMINPKTLEN | \
+        INFINIPATH_E_SPKTLEN)
+
 /*
  * these are errors that can occur when the link changes state while
  * a packet is being sent or received.  This doesn't cover things
@@ -290,12 +303,7 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
                 * Flush all queued sends when link went to DOWN or INIT,
                 * to be sure that they don't block SMA and other MAD packets
                 */
-               ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-                                INFINIPATH_S_ABORT);
-               ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf,
-                                                       (unsigned)(dd->ipath_piobcnt2k +
-                                       dd->ipath_piobcnt4k) -
-                                       dd->ipath_lastport_piobuf);
+               ipath_cancel_sends(dd);
        }
        else if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM ||
            lstate == IPATH_IBSTATE_ACTIVE) {
@@ -505,6 +513,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
        int i, iserr = 0;
        int chkerrpkts = 0, noprint = 0;
        unsigned supp_msgs;
+       int log_idx;
 
        supp_msgs = handle_frequent_errors(dd, errs, msg, &noprint);
 
@@ -518,6 +527,13 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
        if (errs & INFINIPATH_E_HARDWARE) {
                /* reuse same msg buf */
                dd->ipath_f_handle_hwerrors(dd, msg, sizeof msg);
+       } else {
+               u64 mask;
+               for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx) {
+                       mask = dd->ipath_eep_st_masks[log_idx].errs_to_log;
+                       if (errs & mask)
+                               ipath_inc_eeprom_err(dd, log_idx, 1);
+               }
        }
 
        if (!noprint && (errs & ~dd->ipath_e_bitsextant))
@@ -675,6 +691,17 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
                                        chkerrpkts = 1;
                                dd->ipath_lastrcvhdrqtails[i] = tl;
                                pd->port_hdrqfull++;
+                               if (test_bit(IPATH_PORT_WAITING_OVERFLOW,
+                                            &pd->port_flag)) {
+                                       clear_bit(
+                                         IPATH_PORT_WAITING_OVERFLOW,
+                                         &pd->port_flag);
+                                       set_bit(
+                                         IPATH_PORT_WAITING_OVERFLOW,
+                                         &pd->int_flag);
+                                       wake_up_interruptible(
+                                         &pd->port_wait);
+                               }
                        }
                }
        }
@@ -744,6 +771,72 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
        return chkerrpkts;
 }
 
+
+/*
+ * try to cleanup as much as possible for anything that might have gone
+ * wrong while in freeze mode, such as pio buffers being written by user
+ * processes (causing armlaunch), send errors due to going into freeze mode,
+ * etc., and try to avoid causing extra interrupts while doing so.
+ * Forcibly update the in-memory pioavail register copies after cleanup
+ * because the chip won't do it for anything changing while in freeze mode
+ * (we don't want to wait for the next pio buffer state change).
+ * Make sure that we don't lose any important interrupts by using the chip
+ * feature that says that writing 0 to a bit in *clear that is set in
+ * *status will cause an interrupt to be generated again (if allowed by
+ * the *mask value).
+ */
+void ipath_clear_freeze(struct ipath_devdata *dd)
+{
+       int i, im;
+       __le64 val;
+
+       /* disable error interrupts, to avoid confusion */
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
+
+       /*
+        * clear all sends, because they have may been
+        * completed by usercode while in freeze mode, and
+        * therefore would not be sent, and eventually
+        * might cause the process to run out of bufs
+        */
+       ipath_cancel_sends(dd);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+                        dd->ipath_control);
+
+       /* ensure pio avail updates continue */
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+                dd->ipath_sendctrl & ~IPATH_S_PIOBUFAVAILUPD);
+       ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+                dd->ipath_sendctrl);
+
+       /*
+        * We just enabled pioavailupdate, so dma copy is almost certainly
+        * not yet right, so read the registers directly.  Similar to init
+        */
+       for (i = 0; i < dd->ipath_pioavregs; i++) {
+               /* deal with 6110 chip bug */
+               im = i > 3 ? ((i&1) ? i-1 : i+1) : i;
+               val = ipath_read_kreg64(dd, 0x1000+(im*sizeof(u64)));
+               dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i]
+                       = le64_to_cpu(val);
+       }
+
+       /*
+        * force new interrupt if any hwerr, error or interrupt bits are
+        * still set, and clear "safe" send packet errors related to freeze
+        * and cancelling sends.  Re-enable error interrupts before possible
+        * force of re-interrupt on pending interrupts.
+        */
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, 0ULL);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
+               E_SPKT_ERRS_IGNORE);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+               ~dd->ipath_maskederrs);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
+}
+
+
 /* this is separate to allow for better optimization of ipath_intr() */
 
 static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
@@ -872,14 +965,25 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
                   dd->ipath_i_rcvurg_mask);
        for (i = 1; i < dd->ipath_cfgports; i++) {
                struct ipath_portdata *pd = dd->ipath_pd[i];
-               if (portr & (1 << i) && pd && pd->port_cnt &&
-                       test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) {
-                       clear_bit(IPATH_PORT_WAITING_RCV,
-                                 &pd->port_flag);
-                       clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
-                                 &dd->ipath_rcvctrl);
-                       wake_up_interruptible(&pd->port_wait);
-                       rcvdint = 1;
+               if (portr & (1 << i) && pd && pd->port_cnt) {
+                       if (test_bit(IPATH_PORT_WAITING_RCV,
+                                    &pd->port_flag)) {
+                               clear_bit(IPATH_PORT_WAITING_RCV,
+                                         &pd->port_flag);
+                               set_bit(IPATH_PORT_WAITING_RCV,
+                                       &pd->int_flag);
+                               clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
+                                         &dd->ipath_rcvctrl);
+                               wake_up_interruptible(&pd->port_wait);
+                               rcvdint = 1;
+                       } else if (test_bit(IPATH_PORT_WAITING_URG,
+                                           &pd->port_flag)) {
+                               clear_bit(IPATH_PORT_WAITING_URG,
+                                         &pd->port_flag);
+                               set_bit(IPATH_PORT_WAITING_URG,
+                                       &pd->int_flag);
+                               wake_up_interruptible(&pd->port_wait);
+                       }
                }
        }
        if (rcvdint) {
@@ -905,6 +1009,9 @@ irqreturn_t ipath_intr(int irq, void *data)
 
        ipath_stats.sps_ints++;
 
+       if (dd->ipath_int_counter != (u32) -1)
+               dd->ipath_int_counter++;
+
        if (!(dd->ipath_flags & IPATH_PRESENT)) {
                /*
                 * This return value is not great, but we do not want the
index 12194f3dd8cc2b12c9909a3e212b7f8a06c5b93b..3105005fc9d25d0dfd84a5afb93dae7dd6a8bf4a 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _IPATH_KERNEL_H
 #define _IPATH_KERNEL_H
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
 extern struct infinipath_stats ipath_stats;
 
 #define IPATH_CHIP_SWVERSION IPATH_CHIP_VERS_MAJ
+/*
+ * First-cut critierion for "device is active" is
+ * two thousand dwords combined Tx, Rx traffic per
+ * 5-second interval. SMA packets are 64 dwords,
+ * and occur "a few per second", presumably each way.
+ */
+#define IPATH_TRAFFIC_ACTIVE_THRESHOLD (2000)
+/*
+ * Struct used to indicate which errors are logged in each of the
+ * error-counters that are logged to EEPROM. A counter is incremented
+ * _once_ (saturating at 255) for each event with any bits set in
+ * the error or hwerror register masks below.
+ */
+#define IPATH_EEP_LOG_CNT (4)
+struct ipath_eep_log_mask {
+       u64 errs_to_log;
+       u64 hwerrs_to_log;
+};
 
 struct ipath_portdata {
        void **port_rcvegrbuf;
@@ -109,6 +127,8 @@ struct ipath_portdata {
        u32 port_tidcursor;
        /* next expected TID to check */
        unsigned long port_flag;
+       /* what happened */
+       unsigned long int_flag;
        /* WAIT_RCV that timed out, no interrupt */
        u32 port_rcvwait_to;
        /* WAIT_PIO that timed out, no interrupt */
@@ -137,6 +157,8 @@ struct ipath_portdata {
        u32 userversion;
        /* Bitmask of active slaves */
        u32 active_slaves;
+       /* Type of packets or conditions we want to poll for */
+       u16 poll_type;
 };
 
 struct sk_buff;
@@ -275,6 +297,8 @@ struct ipath_devdata {
        u32 ipath_lastport_piobuf;
        /* is a stats timer active */
        u32 ipath_stats_timer_active;
+       /* number of interrupts for this device -- saturates... */
+       u32 ipath_int_counter;
        /* dwords sent read from counter */
        u32 ipath_lastsword;
        /* dwords received read from counter */
@@ -369,9 +393,6 @@ struct ipath_devdata {
        struct class_device *diag_class_dev;
        /* timer used to prevent stats overflow, error throttling, etc. */
        struct timer_list ipath_stats_timer;
-       /* check for stale messages in rcv queue */
-       /* only allow one intr at a time. */
-       unsigned long ipath_rcv_pending;
        void *ipath_dummy_hdrq; /* used after port close */
        dma_addr_t ipath_dummy_hdrq_phys;
 
@@ -399,6 +420,8 @@ struct ipath_devdata {
        u64 ipath_gpio_out;
        /* shadow the gpio mask register */
        u64 ipath_gpio_mask;
+       /* shadow the gpio output enable, etc... */
+       u64 ipath_extctrl;
        /* kr_revision shadow */
        u64 ipath_revision;
        /*
@@ -473,8 +496,6 @@ struct ipath_devdata {
        u32 ipath_cregbase;
        /* shadow the control register contents */
        u32 ipath_control;
-       /* shadow the gpio output contents */
-       u32 ipath_extctrl;
        /* PCI revision register (HTC rev on FPGA) */
        u32 ipath_pcirev;
 
@@ -552,6 +573,9 @@ struct ipath_devdata {
        u32 ipath_overrun_thresh_errs;
        u32 ipath_lli_errs;
 
+       /* status check work */
+       struct delayed_work status_work;
+
        /*
         * Not all devices managed by a driver instance are the same
         * type, so these fields must be per-device.
@@ -575,6 +599,37 @@ struct ipath_devdata {
        u16 ipath_gpio_scl_num;
        u64 ipath_gpio_sda;
        u64 ipath_gpio_scl;
+
+       /* lock for doing RMW of shadows/regs for ExtCtrl and GPIO */
+       spinlock_t ipath_gpio_lock;
+
+       /* used to override LED behavior */
+       u8 ipath_led_override;  /* Substituted for normal value, if non-zero */
+       u16 ipath_led_override_timeoff; /* delta to next timer event */
+       u8 ipath_led_override_vals[2]; /* Alternates per blink-frame */
+       u8 ipath_led_override_phase; /* Just counts, LSB picks from vals[] */
+       atomic_t ipath_led_override_timer_active;
+       /* Used to flash LEDs in override mode */
+       struct timer_list ipath_led_override_timer;
+
+       /* Support (including locks) for EEPROM logging of errors and time */
+       /* control access to actual counters, timer */
+       spinlock_t ipath_eep_st_lock;
+       /* control high-level access to EEPROM */
+       struct semaphore ipath_eep_sem;
+       /* Below inc'd by ipath_snap_cntrs(), locked by ipath_eep_st_lock */
+       uint64_t ipath_traffic_wds;
+       /* active time is kept in seconds, but logged in hours */
+       atomic_t ipath_active_time;
+       /* Below are nominal shadow of EEPROM, new since last EEPROM update */
+       uint8_t ipath_eep_st_errs[IPATH_EEP_LOG_CNT];
+       uint8_t ipath_eep_st_new_errs[IPATH_EEP_LOG_CNT];
+       uint16_t ipath_eep_hrs;
+       /*
+        * masks for which bits of errs, hwerrs that cause
+        * each of the counters to increment.
+        */
+       struct ipath_eep_log_mask ipath_eep_st_masks[IPATH_EEP_LOG_CNT];
 };
 
 /* Private data for file operations */
@@ -592,6 +647,7 @@ int ipath_enable_wc(struct ipath_devdata *dd);
 void ipath_disable_wc(struct ipath_devdata *dd);
 int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
 void ipath_shutdown_device(struct ipath_devdata *);
+void ipath_clear_freeze(struct ipath_devdata *);
 
 struct file_operations;
 int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
@@ -627,6 +683,7 @@ int ipath_unordered_wc(void);
 
 void ipath_disarm_piobufs(struct ipath_devdata *, unsigned first,
                          unsigned cnt);
+void ipath_cancel_sends(struct ipath_devdata *);
 
 int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *);
 void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *);
@@ -685,7 +742,6 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
                 * are 64bit */
 #define IPATH_32BITCOUNTERS 0x20000
                /* can miss port0 rx interrupts */
-#define IPATH_POLL_RX_INTR  0x40000
 #define IPATH_DISABLED      0x80000 /* administratively disabled */
                /* Use GPIO interrupts for new counters */
 #define IPATH_GPIO_ERRINTRS 0x100000
@@ -704,6 +760,10 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
 #define IPATH_PORT_WAITING_PIO   3
                /* master has not finished initializing */
 #define IPATH_PORT_MASTER_UNINIT 4
+               /* waiting for an urgent packet to arrive */
+#define IPATH_PORT_WAITING_URG 5
+               /* waiting for a header overflow */
+#define IPATH_PORT_WAITING_OVERFLOW 6
 
 /* free up any allocated data at closes */
 void ipath_free_data(struct ipath_portdata *dd);
@@ -713,9 +773,20 @@ u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
 void ipath_init_iba6120_funcs(struct ipath_devdata *);
 void ipath_init_iba6110_funcs(struct ipath_devdata *);
 void ipath_get_eeprom_info(struct ipath_devdata *);
+int ipath_update_eeprom_log(struct ipath_devdata *dd);
+void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr);
 u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
 void ipath_disarm_senderrbufs(struct ipath_devdata *, int);
 
+/*
+ * Set LED override, only the two LSBs have "public" meaning, but
+ * any non-zero value substitutes them for the Link and LinkTrain
+ * LED states.
+ */
+#define IPATH_LED_PHYS 1 /* Physical (linktraining) GREEN LED */
+#define IPATH_LED_LOG 2  /* Logical (link) YELLOW LED */
+void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val);
+
 /*
  * number of words used for protocol header if not set by ipath_userinit();
  */
index dd487c100f5ba06865ef0bea3904b05a6520ca0c..85a4aefc6c03cbbb94f63af4eade1f92a36f91fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 05a1d2b01d9dae8be479e912bbc98a5c5e1a83c4..82616b779e2452e6b2fbaaf0cc101c9f5889298b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 3854a4eae68479a75fb614d6807ffae1009946f9..415709c4d85b777dcabc0ae45ee613d51c72d5e7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 25908b02fbe578f57fd6ee7128ea0c9b22169f32..d61c030445451076f1d3fae4d01cde99f034cb44 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -103,7 +103,7 @@ static int recv_subn_get_nodeinfo(struct ib_smp *smp,
        /* This is already in network order */
        nip->sys_guid = to_idev(ibdev)->sys_image_guid;
        nip->node_guid = dd->ipath_guid;
-       nip->port_guid = nip->sys_guid;
+       nip->port_guid = dd->ipath_guid;
        nip->partition_cap = cpu_to_be16(ipath_get_npkeys(dd));
        nip->device_id = cpu_to_be16(dd->ipath_deviceid);
        majrev = dd->ipath_majrev;
@@ -292,7 +292,12 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
        /* pip->vl_arb_high_cap; // only one VL */
        /* pip->vl_arb_low_cap; // only one VL */
        /* InitTypeReply = 0 */
-       pip->inittypereply_mtucap = IB_MTU_4096;
+       /*
+        * Note: the chips support a maximum MTU of 4096, but the driver
+        * hasn't implemented this feature yet, so set the maximum value
+        * to 2048.
+        */
+       pip->inittypereply_mtucap = IB_MTU_2048;
        // HCAs ignore VLStallCount and HOQLife
        /* pip->vlstallcnt_hoqlife; */
        pip->operationalvl_pei_peo_fpi_fpo = 0x10;      /* OVLs = 1 */
index 937bc3396b534420ce90a51f9dd1fe822483738b..fa830e22002fc09d9bcea91f0b908b60558d60f7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. 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 bdeef8d4f279cb5abb8c5954e15dda65a461128d..e442470a23755ff87947434abc21ff39a2d54158 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index bfef08ecd342561b0d1272766564f43a700b1b2a..1324b35ff1f855b460e1a62723cd8f95a1023838 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -336,7 +336,7 @@ static void ipath_reset_qp(struct ipath_qp *qp)
        qp->qkey = 0;
        qp->qp_access_flags = 0;
        qp->s_busy = 0;
-       qp->s_flags &= ~IPATH_S_SIGNAL_REQ_WR;
+       qp->s_flags &= IPATH_S_SIGNAL_REQ_WR;
        qp->s_hdrwords = 0;
        qp->s_psn = 0;
        qp->r_psn = 0;
@@ -507,16 +507,13 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                    attr->port_num > ibqp->device->phys_port_cnt)
                        goto inval;
 
+       /*
+        * Note: the chips support a maximum MTU of 4096, but the driver
+        * hasn't implemented this feature yet, so don't allow Path MTU
+        * values greater than 2048.
+        */
        if (attr_mask & IB_QP_PATH_MTU)
-               if (attr->path_mtu > IB_MTU_4096)
-                       goto inval;
-
-       if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
-               if (attr->max_dest_rd_atomic > 1)
-                       goto inval;
-
-       if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC)
-               if (attr->max_rd_atomic > 1)
+               if (attr->path_mtu > IB_MTU_2048)
                        goto inval;
 
        if (attr_mask & IB_QP_PATH_MIG_STATE)
index 1915771fd038ebaf6204f46b3fcc6ef2e1ffee55..46744ea2babdb336510b3772ed7dfd9fb6d8608c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -125,8 +125,10 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
                        if (len > pmtu) {
                                len = pmtu;
                                qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST);
-                       } else
+                       } else {
                                qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY);
+                               e->sent = 1;
+                       }
                        ohdr->u.aeth = ipath_compute_aeth(qp);
                        hwords++;
                        qp->s_ack_rdma_psn = e->psn;
@@ -143,6 +145,7 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
                                cpu_to_be32(e->atomic_data);
                        hwords += sizeof(ohdr->u.at) / sizeof(u32);
                        bth2 = e->psn;
+                       e->sent = 1;
                }
                bth0 = qp->s_ack_state << 24;
                break;
@@ -158,6 +161,7 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
                        ohdr->u.aeth = ipath_compute_aeth(qp);
                        hwords++;
                        qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST);
+                       qp->s_ack_queue[qp->s_tail_ack_queue].sent = 1;
                }
                bth0 = qp->s_ack_state << 24;
                bth2 = qp->s_ack_rdma_psn++ & IPATH_PSN_MASK;
@@ -188,7 +192,7 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
        }
        qp->s_hdrwords = hwords;
        qp->s_cur_size = len;
-       *bth0p = bth0;
+       *bth0p = bth0 | (1 << 22); /* Set M bit */
        *bth2p = bth2;
        return 1;
 
@@ -240,7 +244,7 @@ int ipath_make_rc_req(struct ipath_qp *qp,
 
        /* header size in 32-bit words LRH+BTH = (8+12)/4. */
        hwords = 5;
-       bth0 = 0;
+       bth0 = 1 << 22; /* Set M bit */
 
        /* Send a request. */
        wqe = get_swqe_ptr(qp, qp->s_cur);
@@ -604,7 +608,7 @@ static void send_rc_ack(struct ipath_qp *qp)
        }
        /* read pkey_index w/o lock (its atomic) */
        bth0 = ipath_get_pkey(dev->dd, qp->s_pkey_index) |
-               OP(ACKNOWLEDGE) << 24;
+               (OP(ACKNOWLEDGE) << 24) | (1 << 22);
        if (qp->r_nak_state)
                ohdr->u.aeth = cpu_to_be32((qp->r_msn & IPATH_MSN_MASK) |
                                            (qp->r_nak_state <<
@@ -806,13 +810,15 @@ static inline void update_last_psn(struct ipath_qp *qp, u32 psn)
  * Called at interrupt level with the QP s_lock held and interrupts disabled.
  * Returns 1 if OK, 0 if current operation should be aborted (NAK).
  */
-static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
+static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode,
+                    u64 val)
 {
        struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
        struct ib_wc wc;
        struct ipath_swqe *wqe;
        int ret = 0;
        u32 ack_psn;
+       int diff;
 
        /*
         * Remove the QP from the timeout queue (or RNR timeout queue).
@@ -840,7 +846,19 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
         * The MSN might be for a later WQE than the PSN indicates so
         * only complete WQEs that the PSN finishes.
         */
-       while (ipath_cmp24(ack_psn, wqe->lpsn) >= 0) {
+       while ((diff = ipath_cmp24(ack_psn, wqe->lpsn)) >= 0) {
+               /*
+                * RDMA_READ_RESPONSE_ONLY is a special case since
+                * we want to generate completion events for everything
+                * before the RDMA read, copy the data, then generate
+                * the completion for the read.
+                */
+               if (wqe->wr.opcode == IB_WR_RDMA_READ &&
+                   opcode == OP(RDMA_READ_RESPONSE_ONLY) &&
+                   diff == 0) {
+                       ret = 1;
+                       goto bail;
+               }
                /*
                 * If this request is a RDMA read or atomic, and the ACK is
                 * for a later operation, this ACK NAKs the RDMA read or
@@ -851,12 +869,10 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
                 * is sent but before the response is received.
                 */
                if ((wqe->wr.opcode == IB_WR_RDMA_READ &&
-                    (opcode != OP(RDMA_READ_RESPONSE_LAST) ||
-                     ipath_cmp24(ack_psn, wqe->lpsn) != 0)) ||
+                    (opcode != OP(RDMA_READ_RESPONSE_LAST) || diff != 0)) ||
                    ((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
                      wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) &&
-                    (opcode != OP(ATOMIC_ACKNOWLEDGE) ||
-                     ipath_cmp24(wqe->psn, psn) != 0))) {
+                    (opcode != OP(ATOMIC_ACKNOWLEDGE) || diff != 0))) {
                        /*
                         * The last valid PSN seen is the previous
                         * request's.
@@ -870,6 +886,9 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
                         */
                        goto bail;
                }
+               if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
+                   wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
+                       *(u64 *) wqe->sg_list[0].vaddr = val;
                if (qp->s_num_rd_atomic &&
                    (wqe->wr.opcode == IB_WR_RDMA_READ ||
                     wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
@@ -1079,6 +1098,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
        int diff;
        u32 pad;
        u32 aeth;
+       u64 val;
 
        spin_lock_irqsave(&qp->s_lock, flags);
 
@@ -1118,8 +1138,6 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
                        data += sizeof(__be32);
                }
                if (opcode == OP(ATOMIC_ACKNOWLEDGE)) {
-                       u64 val;
-
                        if (!header_in_data) {
                                __be32 *p = ohdr->u.at.atomic_ack_eth;
 
@@ -1127,12 +1145,13 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
                                        be32_to_cpu(p[1]);
                        } else
                                val = be64_to_cpu(((__be64 *) data)[0]);
-                       *(u64 *) wqe->sg_list[0].vaddr = val;
-               }
-               if (!do_rc_ack(qp, aeth, psn, opcode) ||
+               } else
+                       val = 0;
+               if (!do_rc_ack(qp, aeth, psn, opcode, val) ||
                    opcode != OP(RDMA_READ_RESPONSE_FIRST))
                        goto ack_done;
                hdrsize += 4;
+               wqe = get_swqe_ptr(qp, qp->s_last);
                if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ))
                        goto ack_op_err;
                /*
@@ -1176,13 +1195,12 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
                goto bail;
 
        case OP(RDMA_READ_RESPONSE_ONLY):
-               if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) {
-                       dev->n_rdma_seq++;
-                       ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+               if (!header_in_data)
+                       aeth = be32_to_cpu(ohdr->u.aeth);
+               else
+                       aeth = be32_to_cpu(((__be32 *) data)[0]);
+               if (!do_rc_ack(qp, aeth, psn, opcode, 0))
                        goto ack_done;
-               }
-               if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ))
-                       goto ack_op_err;
                /* Get the number of bytes the message was padded by. */
                pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
                /*
@@ -1197,6 +1215,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
                 * have to be careful to copy the data to the right
                 * location.
                 */
+               wqe = get_swqe_ptr(qp, qp->s_last);
                qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge,
                                                  wqe, psn, pmtu);
                goto read_last;
@@ -1230,7 +1249,8 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
                        data += sizeof(__be32);
                }
                ipath_copy_sge(&qp->s_rdma_read_sge, data, tlen);
-               (void) do_rc_ack(qp, aeth, psn, OP(RDMA_READ_RESPONSE_LAST));
+               (void) do_rc_ack(qp, aeth, psn,
+                                OP(RDMA_READ_RESPONSE_LAST), 0);
                goto ack_done;
        }
 
@@ -1344,8 +1364,11 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev,
                        e = NULL;
                        break;
                }
-               if (ipath_cmp24(psn, e->psn) >= 0)
+               if (ipath_cmp24(psn, e->psn) >= 0) {
+                       if (prev == qp->s_tail_ack_queue)
+                               old_req = 0;
                        break;
+               }
        }
        switch (opcode) {
        case OP(RDMA_READ_REQUEST): {
@@ -1460,6 +1483,22 @@ static void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err)
        spin_unlock_irqrestore(&qp->s_lock, flags);
 }
 
+static inline void ipath_update_ack_queue(struct ipath_qp *qp, unsigned n)
+{
+       unsigned long flags;
+       unsigned next;
+
+       next = n + 1;
+       if (next > IPATH_MAX_RDMA_ATOMIC)
+               next = 0;
+       spin_lock_irqsave(&qp->s_lock, flags);
+       if (n == qp->s_tail_ack_queue) {
+               qp->s_tail_ack_queue = next;
+               qp->s_ack_state = OP(ACKNOWLEDGE);
+       }
+       spin_unlock_irqrestore(&qp->s_lock, flags);
+}
+
 /**
  * ipath_rc_rcv - process an incoming RC packet
  * @dev: the device this packet came in on
@@ -1672,6 +1711,9 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
        case OP(RDMA_WRITE_FIRST):
        case OP(RDMA_WRITE_ONLY):
        case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE):
+               if (unlikely(!(qp->qp_access_flags &
+                              IB_ACCESS_REMOTE_WRITE)))
+                       goto nack_inv;
                /* consume RWQE */
                /* RETH comes after BTH */
                if (!header_in_data)
@@ -1701,9 +1743,6 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                        qp->r_sge.sge.length = 0;
                        qp->r_sge.sge.sge_length = 0;
                }
-               if (unlikely(!(qp->qp_access_flags &
-                              IB_ACCESS_REMOTE_WRITE)))
-                       goto nack_acc;
                if (opcode == OP(RDMA_WRITE_FIRST))
                        goto send_middle;
                else if (opcode == OP(RDMA_WRITE_ONLY))
@@ -1717,13 +1756,17 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                u32 len;
                u8 next;
 
-               if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ)))
-                       goto nack_acc;
+               if (unlikely(!(qp->qp_access_flags &
+                              IB_ACCESS_REMOTE_READ)))
+                       goto nack_inv;
                next = qp->r_head_ack_queue + 1;
                if (next > IPATH_MAX_RDMA_ATOMIC)
                        next = 0;
-               if (unlikely(next == qp->s_tail_ack_queue))
-                       goto nack_inv;
+               if (unlikely(next == qp->s_tail_ack_queue)) {
+                       if (!qp->s_ack_queue[next].sent)
+                               goto nack_inv;
+                       ipath_update_ack_queue(qp, next);
+               }
                e = &qp->s_ack_queue[qp->r_head_ack_queue];
                /* RETH comes after BTH */
                if (!header_in_data)
@@ -1758,6 +1801,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                        e->rdma_sge.sge.sge_length = 0;
                }
                e->opcode = opcode;
+               e->sent = 0;
                e->psn = psn;
                /*
                 * We need to increment the MSN here instead of when we
@@ -1789,12 +1833,15 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
 
                if (unlikely(!(qp->qp_access_flags &
                               IB_ACCESS_REMOTE_ATOMIC)))
-                       goto nack_acc;
+                       goto nack_inv;
                next = qp->r_head_ack_queue + 1;
                if (next > IPATH_MAX_RDMA_ATOMIC)
                        next = 0;
-               if (unlikely(next == qp->s_tail_ack_queue))
-                       goto nack_inv;
+               if (unlikely(next == qp->s_tail_ack_queue)) {
+                       if (!qp->s_ack_queue[next].sent)
+                               goto nack_inv;
+                       ipath_update_ack_queue(qp, next);
+               }
                if (!header_in_data)
                        ateth = &ohdr->u.atomic_eth;
                else
@@ -1819,6 +1866,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                                      be64_to_cpu(ateth->compare_data),
                                      sdata);
                e->opcode = opcode;
+               e->sent = 0;
                e->psn = psn & IPATH_PSN_MASK;
                qp->r_msn++;
                qp->r_psn++;
index c182bcd62098cd180e4d73c7a4cecd41a3804ba3..708eba3165d764f0c54b45084bb1cfb927b5ff73 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index d9c2a9b15d8686f27ae54e137ecb244ded1b3242..85256747d8a185223da6aaf4eab5dd8287d04908 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -194,6 +194,8 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only)
                        ret = 0;
                        goto bail;
                }
+               /* Make sure entry is read after head index is read. */
+               smp_rmb();
                wqe = get_rwqe_ptr(rq, tail);
                if (++tail >= rq->size)
                        tail = 0;
@@ -267,7 +269,7 @@ again:
        spin_lock_irqsave(&sqp->s_lock, flags);
 
        if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_SEND_OK) ||
-           qp->s_rnr_timeout) {
+           sqp->s_rnr_timeout) {
                spin_unlock_irqrestore(&sqp->s_lock, flags);
                goto done;
        }
@@ -319,12 +321,22 @@ again:
                break;
 
        case IB_WR_RDMA_WRITE_WITH_IMM:
+               if (unlikely(!(qp->qp_access_flags &
+                              IB_ACCESS_REMOTE_WRITE))) {
+                       wc.status = IB_WC_REM_INV_REQ_ERR;
+                       goto err;
+               }
                wc.wc_flags = IB_WC_WITH_IMM;
                wc.imm_data = wqe->wr.imm_data;
                if (!ipath_get_rwqe(qp, 1))
                        goto rnr_nak;
                /* FALLTHROUGH */
        case IB_WR_RDMA_WRITE:
+               if (unlikely(!(qp->qp_access_flags &
+                              IB_ACCESS_REMOTE_WRITE))) {
+                       wc.status = IB_WC_REM_INV_REQ_ERR;
+                       goto err;
+               }
                if (wqe->length == 0)
                        break;
                if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, wqe->length,
@@ -354,8 +366,10 @@ again:
 
        case IB_WR_RDMA_READ:
                if (unlikely(!(qp->qp_access_flags &
-                              IB_ACCESS_REMOTE_READ)))
-                       goto acc_err;
+                              IB_ACCESS_REMOTE_READ))) {
+                       wc.status = IB_WC_REM_INV_REQ_ERR;
+                       goto err;
+               }
                if (unlikely(!ipath_rkey_ok(qp, &sqp->s_sge, wqe->length,
                                            wqe->wr.wr.rdma.remote_addr,
                                            wqe->wr.wr.rdma.rkey,
@@ -369,8 +383,10 @@ again:
        case IB_WR_ATOMIC_CMP_AND_SWP:
        case IB_WR_ATOMIC_FETCH_AND_ADD:
                if (unlikely(!(qp->qp_access_flags &
-                              IB_ACCESS_REMOTE_ATOMIC)))
-                       goto acc_err;
+                              IB_ACCESS_REMOTE_ATOMIC))) {
+                       wc.status = IB_WC_REM_INV_REQ_ERR;
+                       goto err;
+               }
                if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64),
                                            wqe->wr.wr.atomic.remote_addr,
                                            wqe->wr.wr.atomic.rkey,
@@ -396,6 +412,8 @@ again:
 
                if (len > sge->length)
                        len = sge->length;
+               if (len > sge->sge_length)
+                       len = sge->sge_length;
                BUG_ON(len == 0);
                ipath_copy_sge(&qp->r_sge, sge->vaddr, len);
                sge->vaddr += len;
@@ -503,11 +521,9 @@ void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev)
         * could be called.  If we are still in the tasklet function,
         * tasklet_hi_schedule() will not call us until the next time
         * tasklet_hi_schedule() is called.
-        * We clear the tasklet flag now since we are committing to return
-        * from the tasklet function.
+        * We leave the busy flag set so that another post send doesn't
+        * try to put the same QP on the piowait list again.
         */
-       clear_bit(IPATH_S_BUSY, &qp->s_busy);
-       tasklet_unlock(&qp->s_task);
        want_buffer(dev->dd);
        dev->n_piowait++;
 }
index 03acae66ba81a5e0512307f19688c8b18c038b09..40c36ec190167080784383f457dff4c541a21f71 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -80,6 +80,8 @@ int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
                wqe->num_sge = wr->num_sge;
                for (i = 0; i < wr->num_sge; i++)
                        wqe->sg_list[i] = wr->sg_list[i];
+               /* Make sure queue entry is written before the head index. */
+               smp_wmb();
                wq->head = next;
                spin_unlock_irqrestore(&srq->rq.lock, flags);
        }
index d8b5e4cefe250afe961018f219d980ec2eb79306..73ed17d031887cbf5da73d57ee92f0c8b6aeb457 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -55,6 +55,7 @@ u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
        u64 val64;
        unsigned long t0, t1;
        u64 ret;
+       unsigned long flags;
 
        t0 = jiffies;
        /* If fast increment counters are only 32 bits, snapshot them,
@@ -91,12 +92,18 @@ u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
        if (creg == dd->ipath_cregs->cr_wordsendcnt) {
                if (val != dd->ipath_lastsword) {
                        dd->ipath_sword += val - dd->ipath_lastsword;
+                       spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+                       dd->ipath_traffic_wds += val - dd->ipath_lastsword;
+                       spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
                        dd->ipath_lastsword = val;
                }
                val64 = dd->ipath_sword;
        } else if (creg == dd->ipath_cregs->cr_wordrcvcnt) {
                if (val != dd->ipath_lastrword) {
                        dd->ipath_rword += val - dd->ipath_lastrword;
+                       spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+                       dd->ipath_traffic_wds += val - dd->ipath_lastrword;
+                       spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
                        dd->ipath_lastrword = val;
                }
                val64 = dd->ipath_rword;
@@ -200,6 +207,7 @@ void ipath_get_faststats(unsigned long opaque)
        struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
        u32 val;
        static unsigned cnt;
+       unsigned long flags;
 
        /*
         * don't access the chip while running diags, or memory diags can
@@ -210,9 +218,20 @@ void ipath_get_faststats(unsigned long opaque)
                /* but re-arm the timer, for diags case; won't hurt other */
                goto done;
 
+       /*
+        * We now try to maintain a "active timer", based on traffic
+        * exceeding a threshold, so we need to check the word-counts
+        * even if they are 64-bit.
+        */
+       ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
+       ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+       spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+       if (dd->ipath_traffic_wds  >= IPATH_TRAFFIC_ACTIVE_THRESHOLD)
+               atomic_add(5, &dd->ipath_active_time); /* S/B #define */
+       dd->ipath_traffic_wds = 0;
+       spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
+
        if (dd->ipath_flags & IPATH_32BITCOUNTERS) {
-               ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
-               ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
                ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
                ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
        }
index 4dc398d5e01190a29380a7043fc4d2e6410f6e54..16238cd3a036ddcf03899b0f37a91fd85fcd2eba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -596,6 +596,43 @@ bail:
        return ret;
 }
 
+static ssize_t store_led_override(struct device *dev,
+                         struct device_attribute *attr,
+                         const char *buf,
+                         size_t count)
+{
+       struct ipath_devdata *dd = dev_get_drvdata(dev);
+       int ret;
+       u16 val;
+
+       ret = ipath_parse_ushort(buf, &val);
+       if (ret > 0)
+               ipath_set_led_override(dd, val);
+       else
+               ipath_dev_err(dd, "attempt to set invalid LED override\n");
+       return ret;
+}
+
+static ssize_t show_logged_errs(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct ipath_devdata *dd = dev_get_drvdata(dev);
+       int idx, count;
+
+       /* force consistency with actual EEPROM */
+       if (ipath_update_eeprom_log(dd) != 0)
+               return -ENXIO;
+
+       count = 0;
+       for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
+               count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c",
+                       dd->ipath_eep_st_errs[idx],
+                       idx == (IPATH_EEP_LOG_CNT - 1) ? '\n' : ' ');
+       }
+
+       return count;
+}
 
 static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
 static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
@@ -625,6 +662,8 @@ static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL);
 static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
 static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
 static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv);
+static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override);
+static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
 
 static struct attribute *dev_attributes[] = {
        &dev_attr_guid.attr,
@@ -641,6 +680,8 @@ static struct attribute *dev_attributes[] = {
        &dev_attr_unit.attr,
        &dev_attr_enabled.attr,
        &dev_attr_rx_pol_inv.attr,
+       &dev_attr_led_override.attr,
+       &dev_attr_logged_errors.attr,
        NULL
 };
 
index 1c2b03c2ef5e9dd31366f36477132b7b4a8aeada..8380fbc50d2cbe3f9f398cc12d9cd617541f2e7e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -58,7 +58,6 @@ static void complete_last_send(struct ipath_qp *qp, struct ipath_swqe *wqe,
                wc->port_num = 0;
                ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 0);
        }
-       wqe = get_swqe_ptr(qp, qp->s_last);
 }
 
 /**
@@ -87,7 +86,7 @@ int ipath_make_uc_req(struct ipath_qp *qp,
 
        /* header size in 32-bit words LRH+BTH = (8+12)/4. */
        hwords = 5;
-       bth0 = 0;
+       bth0 = 1 << 22; /* Set M bit */
 
        /* Get the next send request. */
        wqe = get_swqe_ptr(qp, qp->s_last);
@@ -97,8 +96,10 @@ int ipath_make_uc_req(struct ipath_qp *qp,
                 * Signal the completion of the last send
                 * (if there is one).
                 */
-               if (qp->s_last != qp->s_tail)
+               if (qp->s_last != qp->s_tail) {
                        complete_last_send(qp, wqe, &wc);
+                       wqe = get_swqe_ptr(qp, qp->s_last);
+               }
 
                /* Check if send work queue is empty. */
                if (qp->s_tail == qp->s_head)
index a518f7c8fa83a9372fc9a5327e646825876261bf..f9a3338a5fb7aa6e90b57c44e88c3b55fe8de87f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -176,6 +176,8 @@ static void ipath_ud_loopback(struct ipath_qp *sqp,
                        dev->n_pkt_drops++;
                        goto bail_sge;
                }
+               /* Make sure entry is read after head index is read. */
+               smp_rmb();
                wqe = get_rwqe_ptr(rq, tail);
                if (++tail >= rq->size)
                        tail = 0;
@@ -231,6 +233,8 @@ static void ipath_ud_loopback(struct ipath_qp *sqp,
 
                if (len > length)
                        len = length;
+               if (len > sge->sge_length)
+                       len = sge->sge_length;
                BUG_ON(len == 0);
                ipath_copy_sge(&rsge, sge->vaddr, len);
                sge->vaddr += len;
index 8536aeb96af862ee2581c307f1ef25155850eb00..27034d38b3ddcadcdcfed50c066081533e8915ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index bb70845279b8148aba4f2dcf4a769b9429efda48..65f7181e9cf81b7e2db757dc188fc6e7dfee0cb6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -164,9 +164,11 @@ void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length)
        while (length) {
                u32 len = sge->length;
 
-               BUG_ON(len == 0);
                if (len > length)
                        len = length;
+               if (len > sge->sge_length)
+                       len = sge->sge_length;
+               BUG_ON(len == 0);
                memcpy(sge->vaddr, data, len);
                sge->vaddr += len;
                sge->length -= len;
@@ -202,9 +204,11 @@ void ipath_skip_sge(struct ipath_sge_state *ss, u32 length)
        while (length) {
                u32 len = sge->length;
 
-               BUG_ON(len == 0);
                if (len > length)
                        len = length;
+               if (len > sge->sge_length)
+                       len = sge->sge_length;
+               BUG_ON(len == 0);
                sge->vaddr += len;
                sge->length -= len;
                sge->sge_length -= len;
@@ -323,6 +327,8 @@ static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
                wqe->num_sge = wr->num_sge;
                for (i = 0; i < wr->num_sge; i++)
                        wqe->sg_list[i] = wr->sg_list[i];
+               /* Make sure queue entry is written before the head index. */
+               smp_wmb();
                wq->head = next;
                spin_unlock_irqrestore(&qp->r_rq.lock, flags);
        }
@@ -948,6 +954,7 @@ int ipath_ib_piobufavail(struct ipath_ibdev *dev)
                qp = list_entry(dev->piowait.next, struct ipath_qp,
                                piowait);
                list_del_init(&qp->piowait);
+               clear_bit(IPATH_S_BUSY, &qp->s_busy);
                tasklet_hi_schedule(&qp->s_task);
        }
        spin_unlock_irqrestore(&dev->pending_lock, flags);
@@ -981,6 +988,8 @@ static int ipath_query_device(struct ib_device *ibdev,
        props->max_ah = ib_ipath_max_ahs;
        props->max_cqe = ib_ipath_max_cqes;
        props->max_mr = dev->lk_table.max;
+       props->max_fmr = dev->lk_table.max;
+       props->max_map_per_fmr = 32767;
        props->max_pd = ib_ipath_max_pds;
        props->max_qp_rd_atom = IPATH_MAX_RDMA_ATOMIC;
        props->max_qp_init_rd_atom = 255;
@@ -1051,7 +1060,12 @@ static int ipath_query_port(struct ib_device *ibdev,
        props->max_vl_num = 1;          /* VLCap = VL0 */
        props->init_type_reply = 0;
 
-       props->max_mtu = IB_MTU_4096;
+       /*
+        * Note: the chips support a maximum MTU of 4096, but the driver
+        * hasn't implemented this feature yet, so set the maximum value
+        * to 2048.
+        */
+       props->max_mtu = IB_MTU_2048;
        switch (dev->dd->ipath_ibmtu) {
        case 4096:
                mtu = IB_MTU_4096;
@@ -1361,13 +1375,6 @@ static void __verbs_timer(unsigned long arg)
 {
        struct ipath_devdata *dd = (struct ipath_devdata *) arg;
 
-       /*
-        * If port 0 receive packet interrupts are not available, or
-        * can be missed, poll the receive queue
-        */
-       if (dd->ipath_flags & IPATH_POLL_RX_INTR)
-               ipath_kreceive(dd);
-
        /* Handle verbs layer timeouts. */
        ipath_ib_timer(dd->verbs_dev);
 
index 088b837ebea8f2c22770f1d578e778d378696224..f3d1f2cee6f8f15ac5cd066e92f79dda3ebf9d3b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -321,6 +321,7 @@ struct ipath_sge_state {
  */
 struct ipath_ack_entry {
        u8 opcode;
+       u8 sent;
        u32 psn;
        union {
                struct ipath_sge_state rdma_sge;
index dd691cfa507932f04ac9b4fb07e163ee18ba19ec..9e5abf9c309d56dca3f42fc8951da8032ad48861 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 0095bb70f34e7bbe1f0257ef13402e69865a8e83..1d7bd82a1fb1fa3ffe8c4cebf08a3cd1b57529ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. 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 04696e62da878ac3322d483bec9d62afbd3c7164..3428acb0868c202383304105546fc023d3a0917e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -63,12 +63,29 @@ int ipath_enable_wc(struct ipath_devdata *dd)
         * of 2 address matching the length (which has to be a power of 2).
         * For rev1, that means the base address, for rev2, it will be just
         * the PIO buffers themselves.
+        * For chips with two sets of buffers, the calculations are
+        * somewhat more complicated; we need to sum, and the piobufbase
+        * register has both offsets, 2K in low 32 bits, 4K in high 32 bits.
+        * The buffers are still packed, so a single range covers both.
         */
-       pioaddr = addr + dd->ipath_piobufbase;
-       piolen = (dd->ipath_piobcnt2k +
-                 dd->ipath_piobcnt4k) *
-               ALIGN(dd->ipath_piobcnt2k +
-                     dd->ipath_piobcnt4k, dd->ipath_palign);
+       if (dd->ipath_piobcnt2k && dd->ipath_piobcnt4k) { /* 2 sizes */
+               unsigned long pio2kbase, pio4kbase;
+               pio2kbase = dd->ipath_piobufbase & 0xffffffffUL;
+               pio4kbase = (dd->ipath_piobufbase >> 32) & 0xffffffffUL;
+               if (pio2kbase < pio4kbase) { /* all, for now */
+                       pioaddr = addr + pio2kbase;
+                       piolen = pio4kbase - pio2kbase +
+                               dd->ipath_piobcnt4k * dd->ipath_4kalign;
+               } else {
+                       pioaddr = addr + pio4kbase;
+                       piolen = pio2kbase - pio4kbase +
+                               dd->ipath_piobcnt2k * dd->ipath_palign;
+               }
+       } else {  /* single buffer size (2K, currently) */
+               pioaddr = addr + dd->ipath_piobufbase;
+               piolen = dd->ipath_piobcnt2k * dd->ipath_palign +
+                       dd->ipath_piobcnt4k * dd->ipath_4kalign;
+       }
 
        for (bits = 0; !(piolen & (1ULL << bits)); bits++)
                /* do nothing */ ;
index b8912cdb966347c4235caec5fedb6833223b7713..4175a4bd0c78841e8d9e121a53a4481069195ef6 100644 (file)
@@ -1,6 +1,5 @@
 config MLX4_INFINIBAND
        tristate "Mellanox ConnectX HCA support"
-       depends on INFINIBAND
        select MLX4_CORE
        ---help---
          This driver provides low-level InfiniBand support for
index c591616dccde7ca0e2632e2b77f4a7e366a2062d..dde8fe9af47e3f24cf13574c363f873a1297fec3 100644 (file)
@@ -169,7 +169,7 @@ static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
        props->phys_state       = out_mad->data[33] >> 4;
        props->port_cap_flags   = be32_to_cpup((__be32 *) (out_mad->data + 20));
        props->gid_tbl_len      = to_mdev(ibdev)->dev->caps.gid_table_len[port];
-       props->max_msg_sz       = 0x80000000;
+       props->max_msg_sz       = to_mdev(ibdev)->dev->caps.max_msg_sz;
        props->pkey_tbl_len     = to_mdev(ibdev)->dev->caps.pkey_table_len[port];
        props->bad_pkey_cntr    = be16_to_cpup((__be16 *) (out_mad->data + 46));
        props->qkey_viol_cntr   = be16_to_cpup((__be16 *) (out_mad->data + 48));
@@ -523,11 +523,13 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                (1ull << IB_USER_VERBS_CMD_DESTROY_CQ)          |
                (1ull << IB_USER_VERBS_CMD_CREATE_QP)           |
                (1ull << IB_USER_VERBS_CMD_MODIFY_QP)           |
+               (1ull << IB_USER_VERBS_CMD_QUERY_QP)            |
                (1ull << IB_USER_VERBS_CMD_DESTROY_QP)          |
                (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST)        |
                (1ull << IB_USER_VERBS_CMD_DETACH_MCAST)        |
                (1ull << IB_USER_VERBS_CMD_CREATE_SRQ)          |
                (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)          |
+               (1ull << IB_USER_VERBS_CMD_QUERY_SRQ)           |
                (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
 
        ibdev->ib_dev.query_device      = mlx4_ib_query_device;
@@ -546,10 +548,12 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        ibdev->ib_dev.destroy_ah        = mlx4_ib_destroy_ah;
        ibdev->ib_dev.create_srq        = mlx4_ib_create_srq;
        ibdev->ib_dev.modify_srq        = mlx4_ib_modify_srq;
+       ibdev->ib_dev.query_srq         = mlx4_ib_query_srq;
        ibdev->ib_dev.destroy_srq       = mlx4_ib_destroy_srq;
        ibdev->ib_dev.post_srq_recv     = mlx4_ib_post_srq_recv;
        ibdev->ib_dev.create_qp         = mlx4_ib_create_qp;
        ibdev->ib_dev.modify_qp         = mlx4_ib_modify_qp;
+       ibdev->ib_dev.query_qp          = mlx4_ib_query_qp;
        ibdev->ib_dev.destroy_qp        = mlx4_ib_destroy_qp;
        ibdev->ib_dev.post_send         = mlx4_ib_post_send;
        ibdev->ib_dev.post_recv         = mlx4_ib_post_recv;
index 24ccadd6e4f84dce47c206e6ac31179dd60f28f4..705ff2fa237e85e73d3ddf8a6e0d8911f737a9e1 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <linux/compiler.h>
 #include <linux/list.h>
+#include <linux/mutex.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_umem.h>
@@ -255,6 +256,7 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
                                  struct ib_udata *udata);
 int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
                       enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
+int mlx4_ib_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
 int mlx4_ib_destroy_srq(struct ib_srq *srq);
 void mlx4_ib_free_srq_wqe(struct mlx4_ib_srq *srq, int wqe_index);
 int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
@@ -266,6 +268,8 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 int mlx4_ib_destroy_qp(struct ib_qp *qp);
 int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                      int attr_mask, struct ib_udata *udata);
+int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask,
+                    struct ib_qp_init_attr *qp_init_attr);
 int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                      struct ib_send_wr **bad_wr);
 int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
index 28a08bdd1800badc5ff207d274055ccd5ae760bd..40042184ad589b0b8b9d124b6622637f11251f02 100644 (file)
@@ -1455,3 +1455,140 @@ out:
 
        return err;
 }
+
+static inline enum ib_qp_state to_ib_qp_state(enum mlx4_qp_state mlx4_state)
+{
+       switch (mlx4_state) {
+       case MLX4_QP_STATE_RST:      return IB_QPS_RESET;
+       case MLX4_QP_STATE_INIT:     return IB_QPS_INIT;
+       case MLX4_QP_STATE_RTR:      return IB_QPS_RTR;
+       case MLX4_QP_STATE_RTS:      return IB_QPS_RTS;
+       case MLX4_QP_STATE_SQ_DRAINING:
+       case MLX4_QP_STATE_SQD:      return IB_QPS_SQD;
+       case MLX4_QP_STATE_SQER:     return IB_QPS_SQE;
+       case MLX4_QP_STATE_ERR:      return IB_QPS_ERR;
+       default:                     return -1;
+       }
+}
+
+static inline enum ib_mig_state to_ib_mig_state(int mlx4_mig_state)
+{
+       switch (mlx4_mig_state) {
+       case MLX4_QP_PM_ARMED:          return IB_MIG_ARMED;
+       case MLX4_QP_PM_REARM:          return IB_MIG_REARM;
+       case MLX4_QP_PM_MIGRATED:       return IB_MIG_MIGRATED;
+       default: return -1;
+       }
+}
+
+static int to_ib_qp_access_flags(int mlx4_flags)
+{
+       int ib_flags = 0;
+
+       if (mlx4_flags & MLX4_QP_BIT_RRE)
+               ib_flags |= IB_ACCESS_REMOTE_READ;
+       if (mlx4_flags & MLX4_QP_BIT_RWE)
+               ib_flags |= IB_ACCESS_REMOTE_WRITE;
+       if (mlx4_flags & MLX4_QP_BIT_RAE)
+               ib_flags |= IB_ACCESS_REMOTE_ATOMIC;
+
+       return ib_flags;
+}
+
+static void to_ib_ah_attr(struct mlx4_dev *dev, struct ib_ah_attr *ib_ah_attr,
+                               struct mlx4_qp_path *path)
+{
+       memset(ib_ah_attr, 0, sizeof *path);
+       ib_ah_attr->port_num      = path->sched_queue & 0x40 ? 2 : 1;
+
+       if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->caps.num_ports)
+               return;
+
+       ib_ah_attr->dlid          = be16_to_cpu(path->rlid);
+       ib_ah_attr->sl            = (path->sched_queue >> 2) & 0xf;
+       ib_ah_attr->src_path_bits = path->grh_mylmc & 0x7f;
+       ib_ah_attr->static_rate   = path->static_rate ? path->static_rate - 5 : 0;
+       ib_ah_attr->ah_flags      = (path->grh_mylmc & (1 << 7)) ? IB_AH_GRH : 0;
+       if (ib_ah_attr->ah_flags) {
+               ib_ah_attr->grh.sgid_index = path->mgid_index;
+               ib_ah_attr->grh.hop_limit  = path->hop_limit;
+               ib_ah_attr->grh.traffic_class =
+                       (be32_to_cpu(path->tclass_flowlabel) >> 20) & 0xff;
+               ib_ah_attr->grh.flow_label =
+                       be32_to_cpu(path->tclass_flowlabel) & 0xffffff;
+               memcpy(ib_ah_attr->grh.dgid.raw,
+                       path->rgid, sizeof ib_ah_attr->grh.dgid.raw);
+       }
+}
+
+int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask,
+                    struct ib_qp_init_attr *qp_init_attr)
+{
+       struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
+       struct mlx4_ib_qp *qp = to_mqp(ibqp);
+       struct mlx4_qp_context context;
+       int mlx4_state;
+       int err;
+
+       if (qp->state == IB_QPS_RESET) {
+               qp_attr->qp_state = IB_QPS_RESET;
+               goto done;
+       }
+
+       err = mlx4_qp_query(dev->dev, &qp->mqp, &context);
+       if (err)
+               return -EINVAL;
+
+       mlx4_state = be32_to_cpu(context.flags) >> 28;
+
+       qp_attr->qp_state            = to_ib_qp_state(mlx4_state);
+       qp_attr->path_mtu            = context.mtu_msgmax >> 5;
+       qp_attr->path_mig_state      =
+               to_ib_mig_state((be32_to_cpu(context.flags) >> 11) & 0x3);
+       qp_attr->qkey                = be32_to_cpu(context.qkey);
+       qp_attr->rq_psn              = be32_to_cpu(context.rnr_nextrecvpsn) & 0xffffff;
+       qp_attr->sq_psn              = be32_to_cpu(context.next_send_psn) & 0xffffff;
+       qp_attr->dest_qp_num         = be32_to_cpu(context.remote_qpn) & 0xffffff;
+       qp_attr->qp_access_flags     =
+               to_ib_qp_access_flags(be32_to_cpu(context.params2));
+
+       if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) {
+               to_ib_ah_attr(dev->dev, &qp_attr->ah_attr, &context.pri_path);
+               to_ib_ah_attr(dev->dev, &qp_attr->alt_ah_attr, &context.alt_path);
+               qp_attr->alt_pkey_index = context.alt_path.pkey_index & 0x7f;
+               qp_attr->alt_port_num   = qp_attr->alt_ah_attr.port_num;
+       }
+
+       qp_attr->pkey_index = context.pri_path.pkey_index & 0x7f;
+       qp_attr->port_num   = context.pri_path.sched_queue & 0x40 ? 2 : 1;
+
+       /* qp_attr->en_sqd_async_notify is only applicable in modify qp */
+       qp_attr->sq_draining = mlx4_state == MLX4_QP_STATE_SQ_DRAINING;
+
+       qp_attr->max_rd_atomic = 1 << ((be32_to_cpu(context.params1) >> 21) & 0x7);
+
+       qp_attr->max_dest_rd_atomic =
+               1 << ((be32_to_cpu(context.params2) >> 21) & 0x7);
+       qp_attr->min_rnr_timer      =
+               (be32_to_cpu(context.rnr_nextrecvpsn) >> 24) & 0x1f;
+       qp_attr->timeout            = context.pri_path.ackto >> 3;
+       qp_attr->retry_cnt          = (be32_to_cpu(context.params1) >> 16) & 0x7;
+       qp_attr->rnr_retry          = (be32_to_cpu(context.params1) >> 13) & 0x7;
+       qp_attr->alt_timeout        = context.alt_path.ackto >> 3;
+
+done:
+       qp_attr->cur_qp_state        = qp_attr->qp_state;
+       if (!ibqp->uobject) {
+               qp_attr->cap.max_send_wr     = qp->sq.wqe_cnt;
+               qp_attr->cap.max_recv_wr     = qp->rq.wqe_cnt;
+               qp_attr->cap.max_send_sge    = qp->sq.max_gs;
+               qp_attr->cap.max_recv_sge    = qp->rq.max_gs;
+               qp_attr->cap.max_inline_data = (1 << qp->sq.wqe_shift) -
+                       send_wqe_overhead(qp->ibqp.qp_type) -
+                       sizeof (struct mlx4_wqe_inline_seg);
+               qp_init_attr->cap            = qp_attr->cap;
+       }
+
+       return 0;
+}
+
index 12fac1c8989dc34bd959aa2735fbf692844c745b..408748fb5285697d24c44b8cd5bebbb19a780f68 100644 (file)
@@ -240,6 +240,24 @@ int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
        return 0;
 }
 
+int mlx4_ib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
+{
+       struct mlx4_ib_dev *dev = to_mdev(ibsrq->device);
+       struct mlx4_ib_srq *srq = to_msrq(ibsrq);
+       int ret;
+       int limit_watermark;
+
+       ret = mlx4_srq_query(dev->dev, &srq->msrq, &limit_watermark);
+       if (ret)
+               return ret;
+
+       srq_attr->srq_limit = be16_to_cpu(limit_watermark);
+       srq_attr->max_wr    = srq->msrq.max - 1;
+       srq_attr->max_sge   = srq->msrq.max_gs;
+
+       return 0;
+}
+
 int mlx4_ib_destroy_srq(struct ib_srq *srq)
 {
        struct mlx4_ib_dev *dev = to_mdev(srq->device);
index 9aa5a4468a753c0ee241277e8d957ffb8207b8d4..03efc074967e2b5344f18acc25f23d2ecf14b2c0 100644 (file)
@@ -1,6 +1,6 @@
 config INFINIBAND_MTHCA
        tristate "Mellanox HCA support"
-       depends on PCI && INFINIBAND
+       depends on PCI
        ---help---
          This is a low-level driver for Mellanox InfiniHost host
          channel adapters (HCAs), including the MT23108 PCI-X HCA
index f930e55b58fcd45ae947b6b29efc9d6efa87dd1c..a763067096182fe14d9502a2a5fdd6135bd6e580 100644 (file)
@@ -255,7 +255,7 @@ int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
                        dma_list[i] = t;
                        pci_unmap_addr_set(&buf->page_list[i], mapping, t);
 
-                       memset(buf->page_list[i].buf, 0, PAGE_SIZE);
+                       clear_page(buf->page_list[i].buf);
                }
        }
 
index 8ec9fa1ff9ea10809ac8dac3e32d904559ff7176..8592b26dc4e1b051d5fe7704e285371145c7587e 100644 (file)
@@ -522,7 +522,7 @@ static int mthca_create_eq(struct mthca_dev *dev,
                dma_list[i] = t;
                pci_unmap_addr_set(&eq->page_list[i], mapping, t);
 
-               memset(eq->page_list[i].buf, 0, PAGE_SIZE);
+               clear_page(eq->page_list[i].buf);
        }
 
        for (i = 0; i < eq->nent; ++i)
index af78ccc4ce7108aba6968b5438a0d8adbc7be4f2..1f76bad020f3f1799025bf7fbad08f1acc7d9489 100644 (file)
@@ -1,6 +1,6 @@
 config INFINIBAND_IPOIB
        tristate "IP-over-InfiniBand"
-       depends on INFINIBAND && NETDEVICES && INET && (IPV6 || IPV6=n)
+       depends on NETDEVICES && INET && (IPV6 || IPV6=n)
        ---help---
          Support for the IP-over-InfiniBand protocol (IPoIB). This
          transports IP packets over InfiniBand so you can use your IB
index ea74d1eaf0046c15c78e6a819067b8743a572a71..08b4676a38201ad94fc5d165ce2a27ed139a36a1 100644 (file)
@@ -281,7 +281,6 @@ static int ipoib_cm_send_rep(struct net_device *dev, struct ib_cm_id *cm_id,
        rep.private_data_len = sizeof data;
        rep.flow_control = 0;
        rep.rnr_retry_count = req->rnr_retry_count;
-       rep.target_ack_delay = 20; /* FIXME */
        rep.srq = 1;
        rep.qp_num = qp->qp_num;
        rep.starting_psn = psn;
@@ -1148,7 +1147,6 @@ static void ipoib_cm_skb_reap(struct work_struct *work)
 {
        struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
                                                   cm.skb_task);
-       struct net_device *dev = priv->dev;
        struct sk_buff *skb;
 
        unsigned mtu = priv->mcast_mtu;
@@ -1162,7 +1160,7 @@ static void ipoib_cm_skb_reap(struct work_struct *work)
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
                else if (skb->protocol == htons(ETH_P_IPV6))
-                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
+                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, priv->dev);
 #endif
                dev_kfree_skb_any(skb);
                spin_lock_irq(&priv->tx_lock);
index 8404f05b2b6eefd04a018b5da67698b65cfb09fd..10944888cffd79de3c8b4751ceac2929a0296141 100644 (file)
@@ -196,6 +196,13 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
                return;
        }
 
+       /*
+        * Drop packets that this interface sent, ie multicast packets
+        * that the HCA has replicated.
+        */
+       if (wc->slid == priv->local_lid && wc->src_qp == priv->qp->qp_num)
+               goto repost;
+
        /*
         * If we can't allocate a new RX buffer, dump
         * this packet and reuse the old buffer.
@@ -213,24 +220,18 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        skb_put(skb, wc->byte_len);
        skb_pull(skb, IB_GRH_BYTES);
 
-       if (wc->slid != priv->local_lid ||
-           wc->src_qp != priv->qp->qp_num) {
-               skb->protocol = ((struct ipoib_header *) skb->data)->proto;
-               skb_reset_mac_header(skb);
-               skb_pull(skb, IPOIB_ENCAP_LEN);
+       skb->protocol = ((struct ipoib_header *) skb->data)->proto;
+       skb_reset_mac_header(skb);
+       skb_pull(skb, IPOIB_ENCAP_LEN);
 
-               dev->last_rx = jiffies;
-               ++priv->stats.rx_packets;
-               priv->stats.rx_bytes += skb->len;
+       dev->last_rx = jiffies;
+       ++priv->stats.rx_packets;
+       priv->stats.rx_bytes += skb->len;
 
-               skb->dev = dev;
-               /* XXX get correct PACKET_ type here */
-               skb->pkt_type = PACKET_HOST;
-               netif_receive_skb(skb);
-       } else {
-               ipoib_dbg_data(priv, "dropping loopback packet\n");
-               dev_kfree_skb_any(skb);
-       }
+       skb->dev = dev;
+       /* XXX get correct PACKET_ type here */
+       skb->pkt_type = PACKET_HOST;
+       netif_receive_skb(skb);
 
 repost:
        if (unlikely(ipoib_ib_post_receive(dev, wr_id)))
index aecbb9083f0c06c770dfb20aba8c1068c9629e1f..fe604c8d299621b9dad04d8e4a9d85672b9ab326 100644 (file)
@@ -1,6 +1,6 @@
 config INFINIBAND_ISER
        tristate "iSCSI Extensions for RDMA (iSER)"
-       depends on INFINIBAND && SCSI && INET
+       depends on SCSI && INET
        select SCSI_ISCSI_ATTRS
        ---help---
          Support for the iSCSI Extensions for RDMA (iSER) Protocol
index 8fe3be4e991081b291d2e724cfe473b1ee8e07ea..3432dce29520a6df599c7a9e7614027257236913 100644 (file)
@@ -1,6 +1,6 @@
 config INFINIBAND_SRP
        tristate "InfiniBand SCSI RDMA Protocol"
-       depends on INFINIBAND && SCSI
+       depends on SCSI
        ---help---
          Support for the SCSI RDMA Protocol over InfiniBand.  This
          allows you to access storage devices that speak SRP over
index 27a68835b5ba1559cd3a498a1730cd18de516d8e..1317bdd8cc7c42c935fac9899c5bdcbda0a5a51b 100644 (file)
@@ -119,7 +119,6 @@ static struct psmouse_attribute psmouse_attr_##_name = {                    \
                .attr   = {                                                     \
                        .name   = __stringify(_name),                           \
                        .mode   = _mode,                                        \
-                       .owner  = THIS_MODULE,                                  \
                },                                                              \
                .show   = psmouse_attr_show_helper,                             \
                .store  = psmouse_attr_set_helper,                              \
index 34031064534612018d85f19e1e914b4e9949ec41..6339bb443f624e56f4fbfe97b3f400d968e5d8ac 100644 (file)
@@ -287,7 +287,6 @@ setup_sct_quadro(struct IsdnCard *card)
 #ifdef CONFIG_PCI
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
-       u_char pci_rev_id;
        u_int found = 0;
        u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5;
 
@@ -335,8 +334,7 @@ setup_sct_quadro(struct IsdnCard *card)
                }
 #ifdef ATTEMPT_PCI_REMAPPING
 /* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */
-               pci_read_config_byte(dev_a8, PCI_REVISION_ID, &pci_rev_id);
-               if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) {
+               if ((pci_ioaddr1 & 0x80) && (dev_a8->revision == 1)) {
                        printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n",
                                CardType[card->typ],
                                sct_quadro_subtypes[cs->subtyp]);
index 11ced17f438a8469a39cf303eda067ff9b21193b..4fcb245ba184edd3d06684f4e2572b5571918212 100644 (file)
@@ -212,7 +212,6 @@ int wf_register_control(struct wf_control *new_ct)
        list_add(&new_ct->link, &wf_controls);
 
        new_ct->attr.attr.name = new_ct->name;
-       new_ct->attr.attr.owner = THIS_MODULE;
        new_ct->attr.attr.mode = 0644;
        new_ct->attr.show = wf_show_control;
        new_ct->attr.store = wf_store_control;
@@ -325,7 +324,6 @@ int wf_register_sensor(struct wf_sensor *new_sr)
        list_add(&new_sr->link, &wf_sensors);
 
        new_sr->attr.attr.name = new_sr->name;
-       new_sr->attr.attr.owner = THIS_MODULE;
        new_sr->attr.attr.mode = 0444;
        new_sr->attr.show = wf_show_sensor;
        new_sr->attr.store = NULL;
index 1043b39aa123e716b67613229e2c34229d1c4274..351982bcec1b21d3a46c767f2879202c73e1419b 100644 (file)
@@ -67,26 +67,6 @@ static struct i2c_driver wf_sat_driver = {
        .detach_client  = wf_sat_detach,
 };
 
-/*
- * XXX i2c_smbus_read_i2c_block_data doesn't pass the requested
- * length down to the low-level driver, so we use this, which
- * works well enough with the SMU i2c driver code...
- */
-static int sat_read_block(struct i2c_client *client, u8 command,
-                         u8 *values, int len)
-{
-       union i2c_smbus_data data;
-       int err;
-
-       data.block[0] = len;
-       err = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
-                            I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA,
-                            &data);
-       if (!err)
-               memcpy(values, data.block, len);
-       return err;
-}
-
 struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
                                                  unsigned int *size)
 {
@@ -124,8 +104,8 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
                return NULL;
 
        for (i = 0; i < len; i += 4) {
-               err = sat_read_block(&sat->i2c, 0xa, data, 4);
-               if (err) {
+               err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data);
+               if (err < 0) {
                        printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n",
                               err);
                        goto fail;
@@ -157,8 +137,8 @@ static int wf_sat_read_cache(struct wf_sat *sat)
 {
        int err;
 
-       err = sat_read_block(&sat->i2c, 0x3f, sat->cache, 16);
-       if (err)
+       err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache);
+       if (err < 0)
                return err;
        sat->last_read = jiffies;
 #ifdef LOTSA_DEBUG
index 7df934d69134436cc2e1f5affb7f681dc0ab1671..64bf3a81db93986573ede44f7300b6440b743bd3 100644 (file)
@@ -109,6 +109,8 @@ config MD_RAID10
 config MD_RAID456
        tristate "RAID-4/RAID-5/RAID-6 mode"
        depends on BLK_DEV_MD
+       select ASYNC_MEMCPY
+       select ASYNC_XOR
        ---help---
          A RAID-5 set of N drives with a capacity of C MB per drive provides
          the capacity of C * (N - 1) MB, and protects against a failure
@@ -262,6 +264,12 @@ config DM_MULTIPATH_EMC
        ---help---
          Multipath support for EMC CX/AX series hardware.
 
+config DM_MULTIPATH_RDAC
+       tristate "LSI/Engenio RDAC multipath support (EXPERIMENTAL)"
+       depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+       ---help---
+         Multipath support for LSI/Engenio RDAC.
+
 config DM_DELAY
        tristate "I/O delaying target (EXPERIMENTAL)"
        depends on BLK_DEV_DM && EXPERIMENTAL
index 38754084eac741462bc677f8c6911b662c719623..c49366cdc05d07e991a081ac55ea4eaf6e8f1b3a 100644 (file)
@@ -7,6 +7,7 @@ dm-mod-objs     := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
 dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
 dm-snapshot-objs := dm-snap.o dm-exception-store.o
 dm-mirror-objs := dm-log.o dm-raid1.o
+dm-rdac-objs   := dm-mpath-rdac.o
 md-mod-objs     := md.o bitmap.o
 raid456-objs   := raid5.o raid6algos.o raid6recov.o raid6tables.o \
                   raid6int1.o raid6int2.o raid6int4.o \
@@ -17,7 +18,7 @@ raid456-objs  := raid5.o raid6algos.o raid6recov.o raid6tables.o \
 hostprogs-y    := mktables
 
 # Note: link order is important.  All raid personalities
-# and xor.o must come before md.o, as they each initialise 
+# and must come before md.o, as they each initialise 
 # themselves, and md.o may use the personalities when it 
 # auto-initialised.
 
@@ -25,7 +26,7 @@ obj-$(CONFIG_MD_LINEAR)               += linear.o
 obj-$(CONFIG_MD_RAID0)         += raid0.o
 obj-$(CONFIG_MD_RAID1)         += raid1.o
 obj-$(CONFIG_MD_RAID10)                += raid10.o
-obj-$(CONFIG_MD_RAID456)       += raid456.o xor.o
+obj-$(CONFIG_MD_RAID456)       += raid456.o
 obj-$(CONFIG_MD_MULTIPATH)     += multipath.o
 obj-$(CONFIG_MD_FAULTY)                += faulty.o
 obj-$(CONFIG_BLK_DEV_MD)       += md-mod.o
@@ -34,6 +35,7 @@ obj-$(CONFIG_DM_CRYPT)                += dm-crypt.o
 obj-$(CONFIG_DM_DELAY)         += dm-delay.o
 obj-$(CONFIG_DM_MULTIPATH)     += dm-multipath.o dm-round-robin.o
 obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o
+obj-$(CONFIG_DM_MULTIPATH_RDAC)        += dm-rdac.o
 obj-$(CONFIG_DM_SNAPSHOT)      += dm-snapshot.o
 obj-$(CONFIG_DM_MIRROR)                += dm-mirror.o
 obj-$(CONFIG_DM_ZERO)          += dm-zero.o
index c6be88826fae4d7aaea55ea0f6f8da7bf3b747ee..16ee3b018b3aa83b80beda532ded23b609b731fb 100644 (file)
@@ -8,7 +8,6 @@
 #define DM_BIO_LIST_H
 
 #include <linux/bio.h>
-#include <linux/prefetch.h>
 
 struct bio_list {
        struct bio *head;
@@ -31,8 +30,7 @@ static inline void bio_list_init(struct bio_list *bl)
 }
 
 #define bio_list_for_each(bio, bl) \
-       for (bio = (bl)->head; bio && ({ prefetch(bio->bi_next); 1; }); \
-            bio = bio->bi_next)
+       for (bio = (bl)->head; bio; bio = bio->bi_next)
 
 static inline unsigned bio_list_size(const struct bio_list *bl)
 {
index 7b0fcfc9eaa5fc0f724d3313360a304b6bbab3a6..ba952a032598c2411bb3f7ff793f6d00baec92bc 100644 (file)
@@ -30,7 +30,7 @@
 /*
  * per bio private data
  */
-struct crypt_io {
+struct dm_crypt_io {
        struct dm_target *target;
        struct bio *base_bio;
        struct work_struct work;
@@ -106,7 +106,7 @@ struct crypt_config {
 
 static struct kmem_cache *_crypt_io_pool;
 
-static void clone_init(struct crypt_io *, struct bio *);
+static void clone_init(struct dm_crypt_io *, struct bio *);
 
 /*
  * Different IV generation algorithms:
@@ -382,7 +382,7 @@ static int crypt_convert(struct crypt_config *cc,
 
  static void dm_crypt_bio_destructor(struct bio *bio)
  {
-       struct crypt_io *io = bio->bi_private;
+       struct dm_crypt_io *io = bio->bi_private;
        struct crypt_config *cc = io->target->private;
 
        bio_free(bio, cc->bs);
@@ -393,7 +393,7 @@ static int crypt_convert(struct crypt_config *cc,
  * This should never violate the device limitations
  * May return a smaller bio when running out of pages
  */
-static struct bio *crypt_alloc_buffer(struct crypt_io *io, unsigned int size)
+static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size)
 {
        struct crypt_config *cc = io->target->private;
        struct bio *clone;
@@ -479,7 +479,7 @@ static void crypt_free_buffer_pages(struct crypt_config *cc,
  * One of the bios was finished. Check for completion of
  * the whole request and correctly clean up the buffer.
  */
-static void dec_pending(struct crypt_io *io, int error)
+static void dec_pending(struct dm_crypt_io *io, int error)
 {
        struct crypt_config *cc = (struct crypt_config *) io->target->private;
 
@@ -503,7 +503,7 @@ static void dec_pending(struct crypt_io *io, int error)
 static struct workqueue_struct *_kcryptd_workqueue;
 static void kcryptd_do_work(struct work_struct *work);
 
-static void kcryptd_queue_io(struct crypt_io *io)
+static void kcryptd_queue_io(struct dm_crypt_io *io)
 {
        INIT_WORK(&io->work, kcryptd_do_work);
        queue_work(_kcryptd_workqueue, &io->work);
@@ -511,7 +511,7 @@ static void kcryptd_queue_io(struct crypt_io *io)
 
 static int crypt_endio(struct bio *clone, unsigned int done, int error)
 {
-       struct crypt_io *io = clone->bi_private;
+       struct dm_crypt_io *io = clone->bi_private;
        struct crypt_config *cc = io->target->private;
        unsigned read_io = bio_data_dir(clone) == READ;
 
@@ -545,7 +545,7 @@ out:
        return error;
 }
 
-static void clone_init(struct crypt_io *io, struct bio *clone)
+static void clone_init(struct dm_crypt_io *io, struct bio *clone)
 {
        struct crypt_config *cc = io->target->private;
 
@@ -556,7 +556,7 @@ static void clone_init(struct crypt_io *io, struct bio *clone)
        clone->bi_destructor = dm_crypt_bio_destructor;
 }
 
-static void process_read(struct crypt_io *io)
+static void process_read(struct dm_crypt_io *io)
 {
        struct crypt_config *cc = io->target->private;
        struct bio *base_bio = io->base_bio;
@@ -587,7 +587,7 @@ static void process_read(struct crypt_io *io)
        generic_make_request(clone);
 }
 
-static void process_write(struct crypt_io *io)
+static void process_write(struct dm_crypt_io *io)
 {
        struct crypt_config *cc = io->target->private;
        struct bio *base_bio = io->base_bio;
@@ -644,7 +644,7 @@ static void process_write(struct crypt_io *io)
        }
 }
 
-static void process_read_endio(struct crypt_io *io)
+static void process_read_endio(struct dm_crypt_io *io)
 {
        struct crypt_config *cc = io->target->private;
        struct convert_context ctx;
@@ -657,7 +657,7 @@ static void process_read_endio(struct crypt_io *io)
 
 static void kcryptd_do_work(struct work_struct *work)
 {
-       struct crypt_io *io = container_of(work, struct crypt_io, work);
+       struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
 
        if (io->post_process)
                process_read_endio(io);
@@ -939,10 +939,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
                     union map_info *map_context)
 {
        struct crypt_config *cc = ti->private;
-       struct crypt_io *io;
-
-       if (bio_barrier(bio))
-               return -EOPNOTSUPP;
+       struct dm_crypt_io *io;
 
        io = mempool_alloc(cc->io_pool, GFP_NOIO);
        io->target = ti;
@@ -1062,9 +1059,7 @@ static int __init dm_crypt_init(void)
 {
        int r;
 
-       _crypt_io_pool = kmem_cache_create("dm-crypt_io",
-                                          sizeof(struct crypt_io),
-                                          0, 0, NULL, NULL);
+       _crypt_io_pool = KMEM_CACHE(dm_crypt_io, 0);
        if (!_crypt_io_pool)
                return -ENOMEM;
 
index 52c7cf9e58036428bea63e9ae9cc56ddf8a37c44..6928c136d3c540d8fdcec9730216f436e1cd9131 100644 (file)
@@ -20,7 +20,7 @@
 
 struct delay_c {
        struct timer_list delay_timer;
-       struct semaphore timer_lock;
+       struct mutex timer_lock;
        struct work_struct flush_expired_bios;
        struct list_head delayed_bios;
        atomic_t may_delay;
@@ -37,7 +37,7 @@ struct delay_c {
        unsigned writes;
 };
 
-struct delay_info {
+struct dm_delay_info {
        struct delay_c *context;
        struct list_head list;
        struct bio *bio;
@@ -58,12 +58,12 @@ static void handle_delayed_timer(unsigned long data)
 
 static void queue_timeout(struct delay_c *dc, unsigned long expires)
 {
-       down(&dc->timer_lock);
+       mutex_lock(&dc->timer_lock);
 
        if (!timer_pending(&dc->delay_timer) || expires < dc->delay_timer.expires)
                mod_timer(&dc->delay_timer, expires);
 
-       up(&dc->timer_lock);
+       mutex_unlock(&dc->timer_lock);
 }
 
 static void flush_bios(struct bio *bio)
@@ -80,7 +80,7 @@ static void flush_bios(struct bio *bio)
 
 static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all)
 {
-       struct delay_info *delayed, *next;
+       struct dm_delay_info *delayed, *next;
        unsigned long next_expires = 0;
        int start_timer = 0;
        BIO_LIST(flush_bios);
@@ -193,13 +193,11 @@ out:
                goto bad;
        }
 
-       init_timer(&dc->delay_timer);
-       dc->delay_timer.function = handle_delayed_timer;
-       dc->delay_timer.data = (unsigned long)dc;
+       setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc);
 
        INIT_WORK(&dc->flush_expired_bios, flush_expired_bios);
        INIT_LIST_HEAD(&dc->delayed_bios);
-       init_MUTEX(&dc->timer_lock);
+       mutex_init(&dc->timer_lock);
        atomic_set(&dc->may_delay, 1);
 
        ti->private = dc;
@@ -227,7 +225,7 @@ static void delay_dtr(struct dm_target *ti)
 
 static int delay_bio(struct delay_c *dc, int delay, struct bio *bio)
 {
-       struct delay_info *delayed;
+       struct dm_delay_info *delayed;
        unsigned long expires = 0;
 
        if (!delay || !atomic_read(&dc->may_delay))
@@ -338,10 +336,7 @@ static int __init dm_delay_init(void)
                goto bad_queue;
        }
 
-       delayed_cache = kmem_cache_create("dm-delay",
-                                         sizeof(struct delay_info),
-                                         __alignof__(struct delay_info),
-                                         0, NULL, NULL);
+       delayed_cache = KMEM_CACHE(dm_delay_info, 0);
        if (!delayed_cache) {
                DMERR("Couldn't create delayed bio cache.");
                goto bad_memcache;
index 07e0a0c84f6ef9f8d93da5b914f22dfc0f9c47fc..3d65917a1bbbe97e2336d75255d97fe7a9ca2bf9 100644 (file)
@@ -125,9 +125,11 @@ struct pstore {
        uint32_t callback_count;
        struct commit_callback *callbacks;
        struct dm_io_client *io_client;
+
+       struct workqueue_struct *metadata_wq;
 };
 
-static inline unsigned int sectors_to_pages(unsigned int sectors)
+static unsigned sectors_to_pages(unsigned sectors)
 {
        return sectors / (PAGE_SIZE >> 9);
 }
@@ -156,10 +158,24 @@ static void free_area(struct pstore *ps)
        ps->area = NULL;
 }
 
+struct mdata_req {
+       struct io_region *where;
+       struct dm_io_request *io_req;
+       struct work_struct work;
+       int result;
+};
+
+static void do_metadata(struct work_struct *work)
+{
+       struct mdata_req *req = container_of(work, struct mdata_req, work);
+
+       req->result = dm_io(req->io_req, 1, req->where, NULL);
+}
+
 /*
  * Read or write a chunk aligned and sized block of data from a device.
  */
-static int chunk_io(struct pstore *ps, uint32_t chunk, int rw)
+static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata)
 {
        struct io_region where = {
                .bdev = ps->snap->cow->bdev,
@@ -173,8 +189,23 @@ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw)
                .client = ps->io_client,
                .notify.fn = NULL,
        };
+       struct mdata_req req;
+
+       if (!metadata)
+               return dm_io(&io_req, 1, &where, NULL);
+
+       req.where = &where;
+       req.io_req = &io_req;
 
-       return dm_io(&io_req, 1, &where, NULL);
+       /*
+        * Issue the synchronous I/O from a different thread
+        * to avoid generic_make_request recursion.
+        */
+       INIT_WORK(&req.work, do_metadata);
+       queue_work(ps->metadata_wq, &req.work);
+       flush_workqueue(ps->metadata_wq);
+
+       return req.result;
 }
 
 /*
@@ -189,7 +220,7 @@ static int area_io(struct pstore *ps, uint32_t area, int rw)
        /* convert a metadata area index to a chunk index */
        chunk = 1 + ((ps->exceptions_per_area + 1) * area);
 
-       r = chunk_io(ps, chunk, rw);
+       r = chunk_io(ps, chunk, rw, 0);
        if (r)
                return r;
 
@@ -230,7 +261,7 @@ static int read_header(struct pstore *ps, int *new_snapshot)
        if (r)
                return r;
 
-       r = chunk_io(ps, 0, READ);
+       r = chunk_io(ps, 0, READ, 1);
        if (r)
                goto bad;
 
@@ -292,7 +323,7 @@ static int write_header(struct pstore *ps)
        dh->version = cpu_to_le32(ps->version);
        dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
 
-       return chunk_io(ps, 0, WRITE);
+       return chunk_io(ps, 0, WRITE, 1);
 }
 
 /*
@@ -393,7 +424,7 @@ static int read_exceptions(struct pstore *ps)
        return 0;
 }
 
-static inline struct pstore *get_info(struct exception_store *store)
+static struct pstore *get_info(struct exception_store *store)
 {
        return (struct pstore *) store->context;
 }
@@ -409,6 +440,7 @@ static void persistent_destroy(struct exception_store *store)
 {
        struct pstore *ps = get_info(store);
 
+       destroy_workqueue(ps->metadata_wq);
        dm_io_client_destroy(ps->io_client);
        vfree(ps->callbacks);
        free_area(ps);
@@ -457,17 +489,18 @@ static int persistent_read_metadata(struct exception_store *store)
                /*
                 * Sanity checks.
                 */
-               if (!ps->valid) {
-                       DMWARN("snapshot is marked invalid");
-                       return -EINVAL;
-               }
-
                if (ps->version != SNAPSHOT_DISK_VERSION) {
                        DMWARN("unable to handle snapshot disk version %d",
                               ps->version);
                        return -EINVAL;
                }
 
+               /*
+                * Metadata are valid, but snapshot is invalidated
+                */
+               if (!ps->valid)
+                       return 1;
+
                /*
                 * Read the metadata.
                 */
@@ -480,7 +513,7 @@ static int persistent_read_metadata(struct exception_store *store)
 }
 
 static int persistent_prepare(struct exception_store *store,
-                             struct exception *e)
+                             struct dm_snap_exception *e)
 {
        struct pstore *ps = get_info(store);
        uint32_t stride;
@@ -505,7 +538,7 @@ static int persistent_prepare(struct exception_store *store,
 }
 
 static void persistent_commit(struct exception_store *store,
-                             struct exception *e,
+                             struct dm_snap_exception *e,
                              void (*callback) (void *, int success),
                              void *callback_context)
 {
@@ -588,6 +621,12 @@ int dm_create_persistent(struct exception_store *store)
        atomic_set(&ps->pending_count, 0);
        ps->callbacks = NULL;
 
+       ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
+       if (!ps->metadata_wq) {
+               DMERR("couldn't start header metadata update thread");
+               return -ENOMEM;
+       }
+
        store->destroy = persistent_destroy;
        store->read_metadata = persistent_read_metadata;
        store->prepare_exception = persistent_prepare;
@@ -616,7 +655,8 @@ static int transient_read_metadata(struct exception_store *store)
        return 0;
 }
 
-static int transient_prepare(struct exception_store *store, struct exception *e)
+static int transient_prepare(struct exception_store *store,
+                            struct dm_snap_exception *e)
 {
        struct transient_c *tc = (struct transient_c *) store->context;
        sector_t size = get_dev_size(store->snap->cow->bdev);
@@ -631,9 +671,9 @@ static int transient_prepare(struct exception_store *store, struct exception *e)
 }
 
 static void transient_commit(struct exception_store *store,
-                     struct exception *e,
-                     void (*callback) (void *, int success),
-                     void *callback_context)
+                            struct dm_snap_exception *e,
+                            void (*callback) (void *, int success),
+                            void *callback_context)
 {
        /* Just succeed */
        callback(callback_context, 1);
index 352c6fbeac53a19dd82f8ef6994b733da4ad931d..f3a772486437e1ee08608e28835adf85911aaaf8 100644 (file)
@@ -293,7 +293,10 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
                 * bvec for bio_get/set_region() and decrement bi_max_vecs
                 * to hide it from bio_add_page().
                 */
-               num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2;
+               num_bvecs = dm_sector_div_up(remaining,
+                                            (PAGE_SIZE >> SECTOR_SHIFT));
+               num_bvecs = 1 + min_t(int, bio_get_nr_vecs(where->bdev),
+                                     num_bvecs);
                bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios);
                bio->bi_sector = where->sector + (where->count - remaining);
                bio->bi_bdev = where->bdev;
diff --git a/drivers/md/dm-mpath-rdac.c b/drivers/md/dm-mpath-rdac.c
new file mode 100644 (file)
index 0000000..8b776b8
--- /dev/null
@@ -0,0 +1,700 @@
+/*
+ * Engenio/LSI RDAC DM HW handler
+ *
+ * Copyright (C) 2005 Mike Christie. All rights reserved.
+ * Copyright (C) Chandra Seetharaman, IBM Corp. 2007
+ *
+ * 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_cmnd.h>
+#include <scsi/scsi_eh.h>
+
+#define DM_MSG_PREFIX "multipath rdac"
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+
+#define RDAC_DM_HWH_NAME "rdac"
+#define RDAC_DM_HWH_VER "0.4"
+
+/*
+ * LSI mode page stuff
+ *
+ * These struct definitions and the forming of the
+ * mode page were taken from the LSI RDAC 2.4 GPL'd
+ * driver, and then converted to Linux conventions.
+ */
+#define RDAC_QUIESCENCE_TIME 20;
+/*
+ * Page Codes
+ */
+#define RDAC_PAGE_CODE_REDUNDANT_CONTROLLER 0x2c
+
+/*
+ * Controller modes definitions
+ */
+#define RDAC_MODE_TRANSFER_ALL_LUNS            0x01
+#define RDAC_MODE_TRANSFER_SPECIFIED_LUNS      0x02
+
+/*
+ * RDAC Options field
+ */
+#define RDAC_FORCED_QUIESENCE 0x02
+
+#define RDAC_FAILOVER_TIMEOUT (60 * HZ)
+
+struct rdac_mode_6_hdr {
+       u8      data_len;
+       u8      medium_type;
+       u8      device_params;
+       u8      block_desc_len;
+};
+
+struct rdac_mode_10_hdr {
+       u16     data_len;
+       u8      medium_type;
+       u8      device_params;
+       u16     reserved;
+       u16     block_desc_len;
+};
+
+struct rdac_mode_common {
+       u8      controller_serial[16];
+       u8      alt_controller_serial[16];
+       u8      rdac_mode[2];
+       u8      alt_rdac_mode[2];
+       u8      quiescence_timeout;
+       u8      rdac_options;
+};
+
+struct rdac_pg_legacy {
+       struct rdac_mode_6_hdr hdr;
+       u8      page_code;
+       u8      page_len;
+       struct rdac_mode_common common;
+#define MODE6_MAX_LUN  32
+       u8      lun_table[MODE6_MAX_LUN];
+       u8      reserved2[32];
+       u8      reserved3;
+       u8      reserved4;
+};
+
+struct rdac_pg_expanded {
+       struct rdac_mode_10_hdr hdr;
+       u8      page_code;
+       u8      subpage_code;
+       u8      page_len[2];
+       struct rdac_mode_common common;
+       u8      lun_table[256];
+       u8      reserved3;
+       u8      reserved4;
+};
+
+struct c9_inquiry {
+       u8      peripheral_info;
+       u8      page_code;      /* 0xC9 */
+       u8      reserved1;
+       u8      page_len;
+       u8      page_id[4];     /* "vace" */
+       u8      avte_cvp;
+       u8      path_prio;
+       u8      reserved2[38];
+};
+
+#define SUBSYS_ID_LEN  16
+#define SLOT_ID_LEN    2
+
+struct c4_inquiry {
+       u8      peripheral_info;
+       u8      page_code;      /* 0xC4 */
+       u8      reserved1;
+       u8      page_len;
+       u8      page_id[4];     /* "subs" */
+       u8      subsys_id[SUBSYS_ID_LEN];
+       u8      revision[4];
+       u8      slot_id[SLOT_ID_LEN];
+       u8      reserved[2];
+};
+
+struct rdac_controller {
+       u8                      subsys_id[SUBSYS_ID_LEN];
+       u8                      slot_id[SLOT_ID_LEN];
+       int                     use_10_ms;
+       struct kref             kref;
+       struct list_head        node; /* list of all controllers */
+       spinlock_t              lock;
+       int                     submitted;
+       struct list_head        cmd_list; /* list of commands to be submitted */
+       union                   {
+               struct rdac_pg_legacy legacy;
+               struct rdac_pg_expanded expanded;
+       } mode_select;
+};
+struct c8_inquiry {
+       u8      peripheral_info;
+       u8      page_code; /* 0xC8 */
+       u8      reserved1;
+       u8      page_len;
+       u8      page_id[4]; /* "edid" */
+       u8      reserved2[3];
+       u8      vol_uniq_id_len;
+       u8      vol_uniq_id[16];
+       u8      vol_user_label_len;
+       u8      vol_user_label[60];
+       u8      array_uniq_id_len;
+       u8      array_unique_id[16];
+       u8      array_user_label_len;
+       u8      array_user_label[60];
+       u8      lun[8];
+};
+
+struct c2_inquiry {
+       u8      peripheral_info;
+       u8      page_code;      /* 0xC2 */
+       u8      reserved1;
+       u8      page_len;
+       u8      page_id[4];     /* "swr4" */
+       u8      sw_version[3];
+       u8      sw_date[3];
+       u8      features_enabled;
+       u8      max_lun_supported;
+       u8      partitions[239]; /* Total allocation length should be 0xFF */
+};
+
+struct rdac_handler {
+       struct list_head        entry; /* list waiting to submit MODE SELECT */
+       unsigned                timeout;
+       struct rdac_controller  *ctlr;
+#define UNINITIALIZED_LUN      (1 << 8)
+       unsigned                lun;
+       unsigned char           sense[SCSI_SENSE_BUFFERSIZE];
+       struct dm_path          *path;
+       struct work_struct      work;
+#define        SEND_C2_INQUIRY         1
+#define        SEND_C4_INQUIRY         2
+#define        SEND_C8_INQUIRY         3
+#define        SEND_C9_INQUIRY         4
+#define        SEND_MODE_SELECT        5
+       int                     cmd_to_send;
+       union                   {
+               struct c2_inquiry c2;
+               struct c4_inquiry c4;
+               struct c8_inquiry c8;
+               struct c9_inquiry c9;
+       } inq;
+};
+
+static LIST_HEAD(ctlr_list);
+static DEFINE_SPINLOCK(list_lock);
+static struct workqueue_struct *rdac_wkqd;
+
+static inline int had_failures(struct request *req, int error)
+{
+       return (error || host_byte(req->errors) != DID_OK ||
+                       msg_byte(req->errors) != COMMAND_COMPLETE);
+}
+
+static void rdac_resubmit_all(struct rdac_handler *h)
+{
+       struct rdac_controller *ctlr = h->ctlr;
+       struct rdac_handler *tmp, *h1;
+
+       spin_lock(&ctlr->lock);
+       list_for_each_entry_safe(h1, tmp, &ctlr->cmd_list, entry) {
+               h1->cmd_to_send = SEND_C9_INQUIRY;
+               queue_work(rdac_wkqd, &h1->work);
+               list_del(&h1->entry);
+       }
+       ctlr->submitted = 0;
+       spin_unlock(&ctlr->lock);
+}
+
+static void mode_select_endio(struct request *req, int error)
+{
+       struct rdac_handler *h = req->end_io_data;
+       struct scsi_sense_hdr sense_hdr;
+       int sense = 0, fail = 0;
+
+       if (had_failures(req, error)) {
+               fail = 1;
+               goto failed;
+       }
+
+       if (status_byte(req->errors) == CHECK_CONDITION) {
+               scsi_normalize_sense(req->sense, SCSI_SENSE_BUFFERSIZE,
+                               &sense_hdr);
+               sense = (sense_hdr.sense_key << 16) | (sense_hdr.asc << 8) |
+                               sense_hdr.ascq;
+               /* If it is retryable failure, submit the c9 inquiry again */
+               if (sense == 0x59136 || sense == 0x68b02 || sense == 0xb8b02 ||
+                   sense == 0x62900) {
+                       /* 0x59136    - Command lock contention
+                        * 0x[6b]8b02 - Quiesense in progress or achieved
+                        * 0x62900    - Power On, Reset, or Bus Device Reset
+                        */
+                       h->cmd_to_send = SEND_C9_INQUIRY;
+                       queue_work(rdac_wkqd, &h->work);
+                       goto done;
+               }
+               if (sense)
+                       DMINFO("MODE_SELECT failed on %s with sense 0x%x",
+                                               h->path->dev->name, sense);
+       }
+failed:
+       if (fail || sense)
+               dm_pg_init_complete(h->path, MP_FAIL_PATH);
+       else
+               dm_pg_init_complete(h->path, 0);
+
+done:
+       rdac_resubmit_all(h);
+       __blk_put_request(req->q, req);
+}
+
+static struct request *get_rdac_req(struct rdac_handler *h,
+                       void *buffer, unsigned buflen, int rw)
+{
+       struct request *rq;
+       struct request_queue *q = bdev_get_queue(h->path->dev->bdev);
+
+       rq = blk_get_request(q, rw, GFP_KERNEL);
+
+       if (!rq) {
+               DMINFO("get_rdac_req: blk_get_request failed");
+               return NULL;
+       }
+
+       if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_KERNEL)) {
+               blk_put_request(rq);
+               DMINFO("get_rdac_req: blk_rq_map_kern failed");
+               return NULL;
+       }
+
+       memset(&rq->cmd, 0, BLK_MAX_CDB);
+       rq->sense = h->sense;
+       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+       rq->sense_len = 0;
+
+       rq->end_io_data = h;
+       rq->timeout = h->timeout;
+       rq->cmd_type = REQ_TYPE_BLOCK_PC;
+       rq->cmd_flags = REQ_FAILFAST | REQ_NOMERGE;
+       return rq;
+}
+
+static struct request *rdac_failover_get(struct rdac_handler *h)
+{
+       struct request *rq;
+       struct rdac_mode_common *common;
+       unsigned data_size;
+
+       if (h->ctlr->use_10_ms) {
+               struct rdac_pg_expanded *rdac_pg;
+
+               data_size = sizeof(struct rdac_pg_expanded);
+               rdac_pg = &h->ctlr->mode_select.expanded;
+               memset(rdac_pg, 0, data_size);
+               common = &rdac_pg->common;
+               rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER + 0x40;
+               rdac_pg->subpage_code = 0x1;
+               rdac_pg->page_len[0] = 0x01;
+               rdac_pg->page_len[1] = 0x28;
+               rdac_pg->lun_table[h->lun] = 0x81;
+       } else {
+               struct rdac_pg_legacy *rdac_pg;
+
+               data_size = sizeof(struct rdac_pg_legacy);
+               rdac_pg = &h->ctlr->mode_select.legacy;
+               memset(rdac_pg, 0, data_size);
+               common = &rdac_pg->common;
+               rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;
+               rdac_pg->page_len = 0x68;
+               rdac_pg->lun_table[h->lun] = 0x81;
+       }
+       common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS;
+       common->quiescence_timeout = RDAC_QUIESCENCE_TIME;
+       common->rdac_options = RDAC_FORCED_QUIESENCE;
+
+       /* get request for block layer packet command */
+       rq = get_rdac_req(h, &h->ctlr->mode_select, data_size, WRITE);
+       if (!rq) {
+               DMERR("rdac_failover_get: no rq");
+               return NULL;
+       }
+
+       /* Prepare the command. */
+       if (h->ctlr->use_10_ms) {
+               rq->cmd[0] = MODE_SELECT_10;
+               rq->cmd[7] = data_size >> 8;
+               rq->cmd[8] = data_size & 0xff;
+       } else {
+               rq->cmd[0] = MODE_SELECT;
+               rq->cmd[4] = data_size;
+       }
+       rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
+
+       return rq;
+}
+
+/* Acquires h->ctlr->lock */
+static void submit_mode_select(struct rdac_handler *h)
+{
+       struct request *rq;
+       struct request_queue *q = bdev_get_queue(h->path->dev->bdev);
+
+       spin_lock(&h->ctlr->lock);
+       if (h->ctlr->submitted) {
+               list_add(&h->entry, &h->ctlr->cmd_list);
+               goto drop_lock;
+       }
+
+       if (!q) {
+               DMINFO("submit_mode_select: no queue");
+               goto fail_path;
+       }
+
+       rq = rdac_failover_get(h);
+       if (!rq) {
+               DMERR("submit_mode_select: no rq");
+               goto fail_path;
+       }
+
+       DMINFO("queueing MODE_SELECT command on %s", h->path->dev->name);
+
+       blk_execute_rq_nowait(q, NULL, rq, 1, mode_select_endio);
+       h->ctlr->submitted = 1;
+       goto drop_lock;
+fail_path:
+       dm_pg_init_complete(h->path, MP_FAIL_PATH);
+drop_lock:
+       spin_unlock(&h->ctlr->lock);
+}
+
+static void release_ctlr(struct kref *kref)
+{
+       struct rdac_controller *ctlr;
+       ctlr = container_of(kref, struct rdac_controller, kref);
+
+       spin_lock(&list_lock);
+       list_del(&ctlr->node);
+       spin_unlock(&list_lock);
+       kfree(ctlr);
+}
+
+static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id)
+{
+       struct rdac_controller *ctlr, *tmp;
+
+       spin_lock(&list_lock);
+
+       list_for_each_entry(tmp, &ctlr_list, node) {
+               if ((memcmp(tmp->subsys_id, subsys_id, SUBSYS_ID_LEN) == 0) &&
+                         (memcmp(tmp->slot_id, slot_id, SLOT_ID_LEN) == 0)) {
+                       kref_get(&tmp->kref);
+                       spin_unlock(&list_lock);
+                       return tmp;
+               }
+       }
+       ctlr = kmalloc(sizeof(*ctlr), GFP_ATOMIC);
+       if (!ctlr)
+               goto done;
+
+       /* initialize fields of controller */
+       memcpy(ctlr->subsys_id, subsys_id, SUBSYS_ID_LEN);
+       memcpy(ctlr->slot_id, slot_id, SLOT_ID_LEN);
+       kref_init(&ctlr->kref);
+       spin_lock_init(&ctlr->lock);
+       ctlr->submitted = 0;
+       ctlr->use_10_ms = -1;
+       INIT_LIST_HEAD(&ctlr->cmd_list);
+       list_add(&ctlr->node, &ctlr_list);
+done:
+       spin_unlock(&list_lock);
+       return ctlr;
+}
+
+static void c4_endio(struct request *req, int error)
+{
+       struct rdac_handler *h = req->end_io_data;
+       struct c4_inquiry *sp;
+
+       if (had_failures(req, error)) {
+               dm_pg_init_complete(h->path, MP_FAIL_PATH);
+               goto done;
+       }
+
+       sp = &h->inq.c4;
+
+       h->ctlr = get_controller(sp->subsys_id, sp->slot_id);
+
+       if (h->ctlr) {
+               h->cmd_to_send = SEND_C9_INQUIRY;
+               queue_work(rdac_wkqd, &h->work);
+       } else
+               dm_pg_init_complete(h->path, MP_FAIL_PATH);
+done:
+       __blk_put_request(req->q, req);
+}
+
+static void c2_endio(struct request *req, int error)
+{
+       struct rdac_handler *h = req->end_io_data;
+       struct c2_inquiry *sp;
+
+       if (had_failures(req, error)) {
+               dm_pg_init_complete(h->path, MP_FAIL_PATH);
+               goto done;
+       }
+
+       sp = &h->inq.c2;
+
+       /* If more than MODE6_MAX_LUN luns are supported, use mode select 10 */
+       if (sp->max_lun_supported >= MODE6_MAX_LUN)
+               h->ctlr->use_10_ms = 1;
+       else
+               h->ctlr->use_10_ms = 0;
+
+       h->cmd_to_send = SEND_MODE_SELECT;
+       queue_work(rdac_wkqd, &h->work);
+done:
+       __blk_put_request(req->q, req);
+}
+
+static void c9_endio(struct request *req, int error)
+{
+       struct rdac_handler *h = req->end_io_data;
+       struct c9_inquiry *sp;
+
+       if (had_failures(req, error)) {
+               dm_pg_init_complete(h->path, MP_FAIL_PATH);
+               goto done;
+       }
+
+       /* We need to look at the sense keys here to take clear action.
+        * For now simple logic: If the host is in AVT mode or if controller
+        * owns the lun, return dm_pg_init_complete(), otherwise submit
+        * MODE SELECT.
+        */
+       sp = &h->inq.c9;
+
+       /* If in AVT mode, return success */
+       if ((sp->avte_cvp >> 7) == 0x1) {
+               dm_pg_init_complete(h->path, 0);
+               goto done;
+       }
+
+       /* If the controller on this path owns the LUN, return success */
+       if (sp->avte_cvp & 0x1) {
+               dm_pg_init_complete(h->path, 0);
+               goto done;
+       }
+
+       if (h->ctlr) {
+               if (h->ctlr->use_10_ms == -1)
+                       h->cmd_to_send = SEND_C2_INQUIRY;
+               else
+                       h->cmd_to_send = SEND_MODE_SELECT;
+       } else
+               h->cmd_to_send = SEND_C4_INQUIRY;
+       queue_work(rdac_wkqd, &h->work);
+done:
+       __blk_put_request(req->q, req);
+}
+
+static void c8_endio(struct request *req, int error)
+{
+       struct rdac_handler *h = req->end_io_data;
+       struct c8_inquiry *sp;
+
+       if (had_failures(req, error)) {
+               dm_pg_init_complete(h->path, MP_FAIL_PATH);
+               goto done;
+       }
+
+       /* We need to look at the sense keys here to take clear action.
+        * For now simple logic: Get the lun from the inquiry page.
+        */
+       sp = &h->inq.c8;
+       h->lun = sp->lun[7]; /* currently it uses only one byte */
+       h->cmd_to_send = SEND_C9_INQUIRY;
+       queue_work(rdac_wkqd, &h->work);
+done:
+       __blk_put_request(req->q, req);
+}
+
+static void submit_inquiry(struct rdac_handler *h, int page_code,
+               unsigned int len, rq_end_io_fn endio)
+{
+       struct request *rq;
+       struct request_queue *q = bdev_get_queue(h->path->dev->bdev);
+
+       if (!q)
+               goto fail_path;
+
+       rq = get_rdac_req(h, &h->inq, len, READ);
+       if (!rq)
+               goto fail_path;
+
+       /* Prepare the command. */
+       rq->cmd[0] = INQUIRY;
+       rq->cmd[1] = 1;
+       rq->cmd[2] = page_code;
+       rq->cmd[4] = len;
+       rq->cmd_len = COMMAND_SIZE(INQUIRY);
+       blk_execute_rq_nowait(q, NULL, rq, 1, endio);
+       return;
+
+fail_path:
+       dm_pg_init_complete(h->path, MP_FAIL_PATH);
+}
+
+static void service_wkq(struct work_struct *work)
+{
+       struct rdac_handler *h = container_of(work, struct rdac_handler, work);
+
+       switch (h->cmd_to_send) {
+       case SEND_C2_INQUIRY:
+               submit_inquiry(h, 0xC2, sizeof(struct c2_inquiry), c2_endio);
+               break;
+       case SEND_C4_INQUIRY:
+               submit_inquiry(h, 0xC4, sizeof(struct c4_inquiry), c4_endio);
+               break;
+       case SEND_C8_INQUIRY:
+               submit_inquiry(h, 0xC8, sizeof(struct c8_inquiry), c8_endio);
+               break;
+       case SEND_C9_INQUIRY:
+               submit_inquiry(h, 0xC9, sizeof(struct c9_inquiry), c9_endio);
+               break;
+       case SEND_MODE_SELECT:
+               submit_mode_select(h);
+               break;
+       default:
+               BUG();
+       }
+}
+/*
+ * only support subpage2c until we confirm that this is just a matter of
+ * of updating firmware or not, and RDAC (basic AVT works already) for now
+ * but we can add these in in when we get time and testers
+ */
+static int rdac_create(struct hw_handler *hwh, unsigned argc, char **argv)
+{
+       struct rdac_handler *h;
+       unsigned timeout;
+
+       if (argc == 0) {
+               /* No arguments: use defaults */
+               timeout = RDAC_FAILOVER_TIMEOUT;
+       } else if (argc != 1) {
+               DMWARN("incorrect number of arguments");
+               return -EINVAL;
+       } else {
+               if (sscanf(argv[1], "%u", &timeout) != 1) {
+                       DMWARN("invalid timeout value");
+                       return -EINVAL;
+               }
+       }
+
+       h = kzalloc(sizeof(*h), GFP_KERNEL);
+       if (!h)
+               return -ENOMEM;
+
+       hwh->context = h;
+       h->timeout = timeout;
+       h->lun = UNINITIALIZED_LUN;
+       INIT_WORK(&h->work, service_wkq);
+       DMWARN("using RDAC command with timeout %u", h->timeout);
+
+       return 0;
+}
+
+static void rdac_destroy(struct hw_handler *hwh)
+{
+       struct rdac_handler *h = hwh->context;
+
+       if (h->ctlr)
+               kref_put(&h->ctlr->kref, release_ctlr);
+       kfree(h);
+       hwh->context = NULL;
+}
+
+static unsigned rdac_error(struct hw_handler *hwh, struct bio *bio)
+{
+       /* Try default handler */
+       return dm_scsi_err_handler(hwh, bio);
+}
+
+static void rdac_pg_init(struct hw_handler *hwh, unsigned bypassed,
+                       struct dm_path *path)
+{
+       struct rdac_handler *h = hwh->context;
+
+       h->path = path;
+       switch (h->lun) {
+       case UNINITIALIZED_LUN:
+               submit_inquiry(h, 0xC8, sizeof(struct c8_inquiry), c8_endio);
+               break;
+       default:
+               submit_inquiry(h, 0xC9, sizeof(struct c9_inquiry), c9_endio);
+       }
+}
+
+static struct hw_handler_type rdac_handler = {
+       .name = RDAC_DM_HWH_NAME,
+       .module = THIS_MODULE,
+       .create = rdac_create,
+       .destroy = rdac_destroy,
+       .pg_init = rdac_pg_init,
+       .error = rdac_error,
+};
+
+static int __init rdac_init(void)
+{
+       int r = dm_register_hw_handler(&rdac_handler);
+
+       if (r < 0) {
+               DMERR("%s: register failed %d", RDAC_DM_HWH_NAME, r);
+               return r;
+       }
+
+       rdac_wkqd = create_singlethread_workqueue("rdac_wkqd");
+       if (!rdac_wkqd) {
+               DMERR("Failed to create workqueue rdac_wkqd.");
+               dm_unregister_hw_handler(&rdac_handler);
+               return -ENOMEM;
+       }
+
+       DMINFO("%s: version %s loaded", RDAC_DM_HWH_NAME, RDAC_DM_HWH_VER);
+       return 0;
+}
+
+static void __exit rdac_exit(void)
+{
+       int r = dm_unregister_hw_handler(&rdac_handler);
+
+       destroy_workqueue(rdac_wkqd);
+       if (r < 0)
+               DMERR("%s: unregister failed %d", RDAC_DM_HWH_NAME, r);
+}
+
+module_init(rdac_init);
+module_exit(rdac_exit);
+
+MODULE_DESCRIPTION("DM Multipath LSI/Engenio RDAC support");
+MODULE_AUTHOR("Mike Christie, Chandra Seetharaman");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RDAC_DM_HWH_VER);
index de54b39e6ffe9fb78cbad18c2a5d5b559d54d870..d6ca9d0a6fd1cbd5fd8f223e9e2b901092e631f3 100644 (file)
@@ -83,7 +83,7 @@ struct multipath {
        struct work_struct trigger_event;
 
        /*
-        * We must use a mempool of mpath_io structs so that we
+        * We must use a mempool of dm_mpath_io structs so that we
         * can resubmit bios on error.
         */
        mempool_t *mpio_pool;
@@ -92,7 +92,7 @@ struct multipath {
 /*
  * Context information attached to each bio we process.
  */
-struct mpath_io {
+struct dm_mpath_io {
        struct pgpath *pgpath;
        struct dm_bio_details details;
 };
@@ -122,7 +122,7 @@ static struct pgpath *alloc_pgpath(void)
        return pgpath;
 }
 
-static inline void free_pgpath(struct pgpath *pgpath)
+static void free_pgpath(struct pgpath *pgpath)
 {
        kfree(pgpath);
 }
@@ -299,8 +299,8 @@ static int __must_push_back(struct multipath *m)
                dm_noflush_suspending(m->ti));
 }
 
-static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
-                 unsigned was_queued)
+static int map_io(struct multipath *m, struct bio *bio,
+                 struct dm_mpath_io *mpio, unsigned was_queued)
 {
        int r = DM_MAPIO_REMAPPED;
        unsigned long flags;
@@ -374,7 +374,7 @@ static void dispatch_queued_ios(struct multipath *m)
        int r;
        unsigned long flags;
        struct bio *bio = NULL, *next;
-       struct mpath_io *mpio;
+       struct dm_mpath_io *mpio;
        union map_info *info;
 
        spin_lock_irqsave(&m->lock, flags);
@@ -795,12 +795,9 @@ static int multipath_map(struct dm_target *ti, struct bio *bio,
                         union map_info *map_context)
 {
        int r;
-       struct mpath_io *mpio;
+       struct dm_mpath_io *mpio;
        struct multipath *m = (struct multipath *) ti->private;
 
-       if (bio_barrier(bio))
-               return -EOPNOTSUPP;
-
        mpio = mempool_alloc(m->mpio_pool, GFP_NOIO);
        dm_bio_record(&mpio->details, bio);
 
@@ -1014,7 +1011,7 @@ void dm_pg_init_complete(struct dm_path *path, unsigned err_flags)
  * end_io handling
  */
 static int do_end_io(struct multipath *m, struct bio *bio,
-                    int error, struct mpath_io *mpio)
+                    int error, struct dm_mpath_io *mpio)
 {
        struct hw_handler *hwh = &m->hw_handler;
        unsigned err_flags = MP_FAIL_PATH;      /* Default behavior */
@@ -1075,8 +1072,8 @@ static int do_end_io(struct multipath *m, struct bio *bio,
 static int multipath_end_io(struct dm_target *ti, struct bio *bio,
                            int error, union map_info *map_context)
 {
-       struct multipath *m = (struct multipath *) ti->private;
-       struct mpath_io *mpio = (struct mpath_io *) map_context->ptr;
+       struct multipath *m = ti->private;
+       struct dm_mpath_io *mpio = map_context->ptr;
        struct pgpath *pgpath = mpio->pgpath;
        struct path_selector *ps;
        int r;
@@ -1346,22 +1343,20 @@ static int __init dm_multipath_init(void)
        int r;
 
        /* allocate a slab for the dm_ios */
-       _mpio_cache = kmem_cache_create("dm_mpath", sizeof(struct mpath_io),
-                                       0, 0, NULL, NULL);
+       _mpio_cache = KMEM_CACHE(dm_mpath_io, 0);
        if (!_mpio_cache)
                return -ENOMEM;
 
        r = dm_register_target(&multipath_target);
        if (r < 0) {
-               DMERR("%s: register failed %d", multipath_target.name, r);
+               DMERR("register failed %d", r);
                kmem_cache_destroy(_mpio_cache);
                return -EINVAL;
        }
 
        kmultipathd = create_workqueue("kmpathd");
        if (!kmultipathd) {
-               DMERR("%s: failed to create workqueue kmpathd",
-                               multipath_target.name);
+               DMERR("failed to create workqueue kmpathd");
                dm_unregister_target(&multipath_target);
                kmem_cache_destroy(_mpio_cache);
                return -ENOMEM;
@@ -1382,8 +1377,7 @@ static void __exit dm_multipath_exit(void)
 
        r = dm_unregister_target(&multipath_target);
        if (r < 0)
-               DMERR("%s: target unregister failed %d",
-                     multipath_target.name, r);
+               DMERR("target unregister failed %d", r);
        kmem_cache_destroy(_mpio_cache);
 }
 
index ef124b71ccc8f1dfd9aa0fdfad0fad81010b0613..1a876f9965e008f9a2008b37806a5fd95443aef8 100644 (file)
@@ -24,6 +24,7 @@
 #define DM_IO_PAGES 64
 
 #define DM_RAID1_HANDLE_ERRORS 0x01
+#define errors_handled(p)      ((p)->features & DM_RAID1_HANDLE_ERRORS)
 
 static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped);
 
@@ -85,6 +86,7 @@ struct region_hash {
        struct list_head clean_regions;
        struct list_head quiesced_regions;
        struct list_head recovered_regions;
+       struct list_head failed_recovered_regions;
 };
 
 enum {
@@ -132,6 +134,7 @@ struct mirror_set {
        /* recovery */
        region_t nr_regions;
        int in_sync;
+       int log_failure;
 
        struct mirror *default_mirror;  /* Default mirror */
 
@@ -204,6 +207,7 @@ static int rh_init(struct region_hash *rh, struct mirror_set *ms,
        INIT_LIST_HEAD(&rh->clean_regions);
        INIT_LIST_HEAD(&rh->quiesced_regions);
        INIT_LIST_HEAD(&rh->recovered_regions);
+       INIT_LIST_HEAD(&rh->failed_recovered_regions);
 
        rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
                                                      sizeof(struct region));
@@ -368,6 +372,7 @@ static void rh_update_states(struct region_hash *rh)
 
        LIST_HEAD(clean);
        LIST_HEAD(recovered);
+       LIST_HEAD(failed_recovered);
 
        /*
         * Quickly grab the lists.
@@ -378,10 +383,8 @@ static void rh_update_states(struct region_hash *rh)
                list_splice(&rh->clean_regions, &clean);
                INIT_LIST_HEAD(&rh->clean_regions);
 
-               list_for_each_entry (reg, &clean, list) {
-                       rh->log->type->clear_region(rh->log, reg->key);
+               list_for_each_entry(reg, &clean, list)
                        list_del(&reg->hash_list);
-               }
        }
 
        if (!list_empty(&rh->recovered_regions)) {
@@ -391,6 +394,15 @@ static void rh_update_states(struct region_hash *rh)
                list_for_each_entry (reg, &recovered, list)
                        list_del(&reg->hash_list);
        }
+
+       if (!list_empty(&rh->failed_recovered_regions)) {
+               list_splice(&rh->failed_recovered_regions, &failed_recovered);
+               INIT_LIST_HEAD(&rh->failed_recovered_regions);
+
+               list_for_each_entry(reg, &failed_recovered, list)
+                       list_del(&reg->hash_list);
+       }
+
        spin_unlock(&rh->region_lock);
        write_unlock_irq(&rh->hash_lock);
 
@@ -405,10 +417,17 @@ static void rh_update_states(struct region_hash *rh)
                mempool_free(reg, rh->region_pool);
        }
 
-       rh->log->type->flush(rh->log);
+       list_for_each_entry_safe(reg, next, &failed_recovered, list) {
+               complete_resync_work(reg, errors_handled(rh->ms) ? 0 : 1);
+               mempool_free(reg, rh->region_pool);
+       }
 
-       list_for_each_entry_safe (reg, next, &clean, list)
+       list_for_each_entry_safe(reg, next, &clean, list) {
+               rh->log->type->clear_region(rh->log, reg->key);
                mempool_free(reg, rh->region_pool);
+       }
+
+       rh->log->type->flush(rh->log);
 }
 
 static void rh_inc(struct region_hash *rh, region_t region)
@@ -555,21 +574,25 @@ static struct region *rh_recovery_start(struct region_hash *rh)
        return reg;
 }
 
-/* FIXME: success ignored for now */
 static void rh_recovery_end(struct region *reg, int success)
 {
        struct region_hash *rh = reg->rh;
 
        spin_lock_irq(&rh->region_lock);
-       list_add(&reg->list, &reg->rh->recovered_regions);
+       if (success)
+               list_add(&reg->list, &reg->rh->recovered_regions);
+       else {
+               reg->state = RH_NOSYNC;
+               list_add(&reg->list, &reg->rh->failed_recovered_regions);
+       }
        spin_unlock_irq(&rh->region_lock);
 
        wake(rh->ms);
 }
 
-static void rh_flush(struct region_hash *rh)
+static int rh_flush(struct region_hash *rh)
 {
-       rh->log->type->flush(rh->log);
+       return rh->log->type->flush(rh->log);
 }
 
 static void rh_delay(struct region_hash *rh, struct bio *bio)
@@ -633,7 +656,14 @@ static void recovery_complete(int read_err, unsigned int write_err,
 {
        struct region *reg = (struct region *) context;
 
-       /* FIXME: better error handling */
+       if (read_err)
+               /* Read error means the failure of default mirror. */
+               DMERR_LIMIT("Unable to read primary mirror during recovery");
+
+       if (write_err)
+               DMERR_LIMIT("Write error during recovery (error = 0x%x)",
+                           write_err);
+
        rh_recovery_end(reg, !(read_err || write_err));
 }
 
@@ -863,12 +893,15 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
         */
        rh_inc_pending(&ms->rh, &sync);
        rh_inc_pending(&ms->rh, &nosync);
-       rh_flush(&ms->rh);
+       ms->log_failure = rh_flush(&ms->rh) ? 1 : 0;
 
        /*
         * Dispatch io.
         */
-       while ((bio = bio_list_pop(&sync)))
+       if (unlikely(ms->log_failure))
+               while ((bio = bio_list_pop(&sync)))
+                       bio_endio(bio, bio->bi_size, -EIO);
+       else while ((bio = bio_list_pop(&sync)))
                do_write(ms, bio);
 
        while ((bio = bio_list_pop(&recover)))
@@ -1145,6 +1178,15 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        argv += args_used;
        argc -= args_used;
 
+       /*
+        * Any read-balancing addition depends on the
+        * DM_RAID1_HANDLE_ERRORS flag being present.
+        * This is because the decision to balance depends
+        * on the sync state of a region.  If the above
+        * flag is not present, we ignore errors; and
+        * the sync state may be inaccurate.
+        */
+
        if (argc) {
                ti->error = "Too many mirror arguments";
                free_context(ms, ti, ms->nr_mirrors);
@@ -1288,12 +1330,12 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
                for (m = 0; m < ms->nr_mirrors; m++)
                        DMEMIT("%s ", ms->mirror[m].dev->name);
 
-               DMEMIT("%llu/%llu",
+               DMEMIT("%llu/%llu 0 ",
                        (unsigned long long)ms->rh.log->type->
                                get_sync_count(ms->rh.log),
                        (unsigned long long)ms->nr_regions);
 
-               sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen);
+               sz += ms->rh.log->type->status(ms->rh.log, type, result+sz, maxlen-sz);
 
                break;
 
@@ -1335,8 +1377,7 @@ static int __init dm_mirror_init(void)
 
        r = dm_register_target(&mirror_target);
        if (r < 0) {
-               DMERR("%s: Failed to register mirror target",
-                     mirror_target.name);
+               DMERR("Failed to register mirror target");
                dm_dirty_log_exit();
        }
 
@@ -1349,7 +1390,7 @@ static void __exit dm_mirror_exit(void)
 
        r = dm_unregister_target(&mirror_target);
        if (r < 0)
-               DMERR("%s: unregister failed %d", mirror_target.name, r);
+               DMERR("unregister failed %d", r);
 
        dm_dirty_log_exit();
 }
index a348a97b65af3f243e2a8b11433e612df2d0856b..391dfa2ad4347a690d8bc4636515ebfff39a5f08 100644 (file)
@@ -205,7 +205,7 @@ static void __exit dm_rr_exit(void)
        int r = dm_unregister_path_selector(&rr_ps);
 
        if (r < 0)
-               DMERR("round-robin: unregister failed %d", r);
+               DMERR("unregister failed %d", r);
 }
 
 module_init(dm_rr_init);
index 0821a2b68a73a98719cb931c82196a74bfe471d4..83ddbfe6b8a415ca492c2db7b4701c1492a2a623 100644 (file)
@@ -42,8 +42,8 @@
 static struct workqueue_struct *ksnapd;
 static void flush_queued_bios(struct work_struct *work);
 
-struct pending_exception {
-       struct exception e;
+struct dm_snap_pending_exception {
+       struct dm_snap_exception e;
 
        /*
         * Origin buffers waiting for this to complete are held
@@ -63,7 +63,7 @@ struct pending_exception {
         * group of pending_exceptions.  It is always last to get freed.
         * These fields get set up when writing to the origin.
         */
-       struct pending_exception *primary_pe;
+       struct dm_snap_pending_exception *primary_pe;
 
        /*
         * Number of pending_exceptions processing this chunk.
@@ -137,7 +137,7 @@ static void exit_origin_hash(void)
        kfree(_origins);
 }
 
-static inline unsigned int origin_hash(struct block_device *bdev)
+static unsigned origin_hash(struct block_device *bdev)
 {
        return bdev->bd_dev & ORIGIN_MASK;
 }
@@ -231,7 +231,7 @@ static int init_exception_table(struct exception_table *et, uint32_t size)
 static void exit_exception_table(struct exception_table *et, struct kmem_cache *mem)
 {
        struct list_head *slot;
-       struct exception *ex, *next;
+       struct dm_snap_exception *ex, *next;
        int i, size;
 
        size = et->hash_mask + 1;
@@ -245,18 +245,19 @@ static void exit_exception_table(struct exception_table *et, struct kmem_cache *
        vfree(et->table);
 }
 
-static inline uint32_t exception_hash(struct exception_table *et, chunk_t chunk)
+static uint32_t exception_hash(struct exception_table *et, chunk_t chunk)
 {
        return chunk & et->hash_mask;
 }
 
-static void insert_exception(struct exception_table *eh, struct exception *e)
+static void insert_exception(struct exception_table *eh,
+                            struct dm_snap_exception *e)
 {
        struct list_head *l = &eh->table[exception_hash(eh, e->old_chunk)];
        list_add(&e->hash_list, l);
 }
 
-static inline void remove_exception(struct exception *e)
+static void remove_exception(struct dm_snap_exception *e)
 {
        list_del(&e->hash_list);
 }
@@ -265,11 +266,11 @@ static inline void remove_exception(struct exception *e)
  * Return the exception data for a sector, or NULL if not
  * remapped.
  */
-static struct exception *lookup_exception(struct exception_table *et,
-                                         chunk_t chunk)
+static struct dm_snap_exception *lookup_exception(struct exception_table *et,
+                                                 chunk_t chunk)
 {
        struct list_head *slot;
-       struct exception *e;
+       struct dm_snap_exception *e;
 
        slot = &et->table[exception_hash(et, chunk)];
        list_for_each_entry (e, slot, hash_list)
@@ -279,9 +280,9 @@ static struct exception *lookup_exception(struct exception_table *et,
        return NULL;
 }
 
-static inline struct exception *alloc_exception(void)
+static struct dm_snap_exception *alloc_exception(void)
 {
-       struct exception *e;
+       struct dm_snap_exception *e;
 
        e = kmem_cache_alloc(exception_cache, GFP_NOIO);
        if (!e)
@@ -290,24 +291,24 @@ static inline struct exception *alloc_exception(void)
        return e;
 }
 
-static inline void free_exception(struct exception *e)
+static void free_exception(struct dm_snap_exception *e)
 {
        kmem_cache_free(exception_cache, e);
 }
 
-static inline struct pending_exception *alloc_pending_exception(void)
+static struct dm_snap_pending_exception *alloc_pending_exception(void)
 {
        return mempool_alloc(pending_pool, GFP_NOIO);
 }
 
-static inline void free_pending_exception(struct pending_exception *pe)
+static void free_pending_exception(struct dm_snap_pending_exception *pe)
 {
        mempool_free(pe, pending_pool);
 }
 
 int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new)
 {
-       struct exception *e;
+       struct dm_snap_exception *e;
 
        e = alloc_exception();
        if (!e)
@@ -334,7 +335,7 @@ static int calc_max_buckets(void)
 /*
  * Rounds a number down to a power of 2.
  */
-static inline uint32_t round_down(uint32_t n)
+static uint32_t round_down(uint32_t n)
 {
        while (n & (n - 1))
                n &= (n - 1);
@@ -384,7 +385,7 @@ static int init_hash_tables(struct dm_snapshot *s)
  * Round a number up to the nearest 'size' boundary.  size must
  * be a power of 2.
  */
-static inline ulong round_up(ulong n, ulong size)
+static ulong round_up(ulong n, ulong size)
 {
        size--;
        return (n + size) & ~size;
@@ -522,9 +523,12 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        /* Metadata must only be loaded into one table at once */
        r = s->store.read_metadata(&s->store);
-       if (r) {
+       if (r < 0) {
                ti->error = "Failed to read snapshot metadata";
                goto bad6;
+       } else if (r > 0) {
+               s->valid = 0;
+               DMWARN("Snapshot is marked invalid.");
        }
 
        bio_list_init(&s->queued_bios);
@@ -577,7 +581,7 @@ static void __free_exceptions(struct dm_snapshot *s)
 
 static void snapshot_dtr(struct dm_target *ti)
 {
-       struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+       struct dm_snapshot *s = ti->private;
 
        flush_workqueue(ksnapd);
 
@@ -655,14 +659,14 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err)
        dm_table_event(s->table);
 }
 
-static void get_pending_exception(struct pending_exception *pe)
+static void get_pending_exception(struct dm_snap_pending_exception *pe)
 {
        atomic_inc(&pe->ref_count);
 }
 
-static struct bio *put_pending_exception(struct pending_exception *pe)
+static struct bio *put_pending_exception(struct dm_snap_pending_exception *pe)
 {
-       struct pending_exception *primary_pe;
+       struct dm_snap_pending_exception *primary_pe;
        struct bio *origin_bios = NULL;
 
        primary_pe = pe->primary_pe;
@@ -692,9 +696,9 @@ static struct bio *put_pending_exception(struct pending_exception *pe)
        return origin_bios;
 }
 
-static void pending_complete(struct pending_exception *pe, int success)
+static void pending_complete(struct dm_snap_pending_exception *pe, int success)
 {
-       struct exception *e;
+       struct dm_snap_exception *e;
        struct dm_snapshot *s = pe->snap;
        struct bio *origin_bios = NULL;
        struct bio *snapshot_bios = NULL;
@@ -748,7 +752,8 @@ static void pending_complete(struct pending_exception *pe, int success)
 
 static void commit_callback(void *context, int success)
 {
-       struct pending_exception *pe = (struct pending_exception *) context;
+       struct dm_snap_pending_exception *pe = context;
+
        pending_complete(pe, success);
 }
 
@@ -758,7 +763,7 @@ static void commit_callback(void *context, int success)
  */
 static void copy_callback(int read_err, unsigned int write_err, void *context)
 {
-       struct pending_exception *pe = (struct pending_exception *) context;
+       struct dm_snap_pending_exception *pe = context;
        struct dm_snapshot *s = pe->snap;
 
        if (read_err || write_err)
@@ -773,7 +778,7 @@ static void copy_callback(int read_err, unsigned int write_err, void *context)
 /*
  * Dispatches the copy operation to kcopyd.
  */
-static void start_copy(struct pending_exception *pe)
+static void start_copy(struct dm_snap_pending_exception *pe)
 {
        struct dm_snapshot *s = pe->snap;
        struct io_region src, dest;
@@ -803,11 +808,11 @@ static void start_copy(struct pending_exception *pe)
  * NOTE: a write lock must be held on snap->lock before calling
  * this.
  */
-static struct pending_exception *
+static struct dm_snap_pending_exception *
 __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
 {
-       struct exception *e;
-       struct pending_exception *pe;
+       struct dm_snap_exception *e;
+       struct dm_snap_pending_exception *pe;
        chunk_t chunk = sector_to_chunk(s, bio->bi_sector);
 
        /*
@@ -816,7 +821,7 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
        e = lookup_exception(&s->pending, chunk);
        if (e) {
                /* cast the exception to a pending exception */
-               pe = container_of(e, struct pending_exception, e);
+               pe = container_of(e, struct dm_snap_pending_exception, e);
                goto out;
        }
 
@@ -836,7 +841,7 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
        e = lookup_exception(&s->pending, chunk);
        if (e) {
                free_pending_exception(pe);
-               pe = container_of(e, struct pending_exception, e);
+               pe = container_of(e, struct dm_snap_pending_exception, e);
                goto out;
        }
 
@@ -860,8 +865,8 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
        return pe;
 }
 
-static inline void remap_exception(struct dm_snapshot *s, struct exception *e,
-                                  struct bio *bio)
+static void remap_exception(struct dm_snapshot *s, struct dm_snap_exception *e,
+                           struct bio *bio)
 {
        bio->bi_bdev = s->cow->bdev;
        bio->bi_sector = chunk_to_sector(s, e->new_chunk) +
@@ -871,11 +876,11 @@ static inline void remap_exception(struct dm_snapshot *s, struct exception *e,
 static int snapshot_map(struct dm_target *ti, struct bio *bio,
                        union map_info *map_context)
 {
-       struct exception *e;
-       struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+       struct dm_snap_exception *e;
+       struct dm_snapshot *s = ti->private;
        int r = DM_MAPIO_REMAPPED;
        chunk_t chunk;
-       struct pending_exception *pe = NULL;
+       struct dm_snap_pending_exception *pe = NULL;
 
        chunk = sector_to_chunk(s, bio->bi_sector);
 
@@ -884,9 +889,6 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
        if (!s->valid)
                return -EIO;
 
-       if (unlikely(bio_barrier(bio)))
-               return -EOPNOTSUPP;
-
        /* FIXME: should only take write lock if we need
         * to copy an exception */
        down_write(&s->lock);
@@ -945,7 +947,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
 
 static void snapshot_resume(struct dm_target *ti)
 {
-       struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+       struct dm_snapshot *s = ti->private;
 
        down_write(&s->lock);
        s->active = 1;
@@ -955,7 +957,7 @@ static void snapshot_resume(struct dm_target *ti)
 static int snapshot_status(struct dm_target *ti, status_type_t type,
                           char *result, unsigned int maxlen)
 {
-       struct dm_snapshot *snap = (struct dm_snapshot *) ti->private;
+       struct dm_snapshot *snap = ti->private;
 
        switch (type) {
        case STATUSTYPE_INFO:
@@ -999,8 +1001,8 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
 {
        int r = DM_MAPIO_REMAPPED, first = 0;
        struct dm_snapshot *snap;
-       struct exception *e;
-       struct pending_exception *pe, *next_pe, *primary_pe = NULL;
+       struct dm_snap_exception *e;
+       struct dm_snap_pending_exception *pe, *next_pe, *primary_pe = NULL;
        chunk_t chunk;
        LIST_HEAD(pe_queue);
 
@@ -1147,19 +1149,16 @@ static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
 static void origin_dtr(struct dm_target *ti)
 {
-       struct dm_dev *dev = (struct dm_dev *) ti->private;
+       struct dm_dev *dev = ti->private;
        dm_put_device(ti, dev);
 }
 
 static int origin_map(struct dm_target *ti, struct bio *bio,
                      union map_info *map_context)
 {
-       struct dm_dev *dev = (struct dm_dev *) ti->private;
+       struct dm_dev *dev = ti->private;
        bio->bi_bdev = dev->bdev;
 
-       if (unlikely(bio_barrier(bio)))
-               return -EOPNOTSUPP;
-
        /* Only tell snapshots if this is a write */
        return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED;
 }
@@ -1172,7 +1171,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio,
  */
 static void origin_resume(struct dm_target *ti)
 {
-       struct dm_dev *dev = (struct dm_dev *) ti->private;
+       struct dm_dev *dev = ti->private;
        struct dm_snapshot *snap;
        struct origin *o;
        chunk_t chunk_size = 0;
@@ -1190,7 +1189,7 @@ static void origin_resume(struct dm_target *ti)
 static int origin_status(struct dm_target *ti, status_type_t type, char *result,
                         unsigned int maxlen)
 {
-       struct dm_dev *dev = (struct dm_dev *) ti->private;
+       struct dm_dev *dev = ti->private;
 
        switch (type) {
        case STATUSTYPE_INFO:
@@ -1249,21 +1248,14 @@ static int __init dm_snapshot_init(void)
                goto bad2;
        }
 
-       exception_cache = kmem_cache_create("dm-snapshot-ex",
-                                           sizeof(struct exception),
-                                           __alignof__(struct exception),
-                                           0, NULL, NULL);
+       exception_cache = KMEM_CACHE(dm_snap_exception, 0);
        if (!exception_cache) {
                DMERR("Couldn't create exception cache.");
                r = -ENOMEM;
                goto bad3;
        }
 
-       pending_cache =
-           kmem_cache_create("dm-snapshot-in",
-                             sizeof(struct pending_exception),
-                             __alignof__(struct pending_exception),
-                             0, NULL, NULL);
+       pending_cache = KMEM_CACHE(dm_snap_pending_exception, 0);
        if (!pending_cache) {
                DMERR("Couldn't create pending cache.");
                r = -ENOMEM;
index 15fa2ae6cdc2971f590a814578d06536b75b8484..650e0f1f51d8a6c312a001c8443cf3bc8064d481 100644 (file)
@@ -30,7 +30,7 @@ typedef sector_t chunk_t;
  * An exception is used where an old chunk of data has been
  * replaced by a new one.
  */
-struct exception {
+struct dm_snap_exception {
        struct list_head hash_list;
 
        chunk_t old_chunk;
@@ -58,13 +58,13 @@ struct exception_store {
         * Find somewhere to store the next exception.
         */
        int (*prepare_exception) (struct exception_store *store,
-                                 struct exception *e);
+                                 struct dm_snap_exception *e);
 
        /*
         * Update the metadata with this exception.
         */
        void (*commit_exception) (struct exception_store *store,
-                                 struct exception *e,
+                                 struct dm_snap_exception *e,
                                  void (*callback) (void *, int success),
                                  void *callback_context);
 
index 2717a355dc5bf6847243de88f78fd540da5e941b..f4f7d35561ab83753f03fe16a186514514916bf6 100644 (file)
@@ -45,7 +45,7 @@ struct dm_io {
  * One of these is allocated per target within a bio.  Hopefully
  * this will be simplified out one day.
  */
-struct target_io {
+struct dm_target_io {
        struct dm_io *io;
        struct dm_target *ti;
        union map_info info;
@@ -54,7 +54,7 @@ struct target_io {
 union map_info *dm_get_mapinfo(struct bio *bio)
 {
        if (bio && bio->bi_private)
-               return &((struct target_io *)bio->bi_private)->info;
+               return &((struct dm_target_io *)bio->bi_private)->info;
        return NULL;
 }
 
@@ -132,14 +132,12 @@ static int __init local_init(void)
        int r;
 
        /* allocate a slab for the dm_ios */
-       _io_cache = kmem_cache_create("dm_io",
-                                     sizeof(struct dm_io), 0, 0, NULL, NULL);
+       _io_cache = KMEM_CACHE(dm_io, 0);
        if (!_io_cache)
                return -ENOMEM;
 
        /* allocate a slab for the target ios */
-       _tio_cache = kmem_cache_create("dm_tio", sizeof(struct target_io),
-                                      0, 0, NULL, NULL);
+       _tio_cache = KMEM_CACHE(dm_target_io, 0);
        if (!_tio_cache) {
                kmem_cache_destroy(_io_cache);
                return -ENOMEM;
@@ -325,22 +323,22 @@ out:
        return r;
 }
 
-static inline struct dm_io *alloc_io(struct mapped_device *md)
+static struct dm_io *alloc_io(struct mapped_device *md)
 {
        return mempool_alloc(md->io_pool, GFP_NOIO);
 }
 
-static inline void free_io(struct mapped_device *md, struct dm_io *io)
+static void free_io(struct mapped_device *md, struct dm_io *io)
 {
        mempool_free(io, md->io_pool);
 }
 
-static inline struct target_io *alloc_tio(struct mapped_device *md)
+static struct dm_target_io *alloc_tio(struct mapped_device *md)
 {
        return mempool_alloc(md->tio_pool, GFP_NOIO);
 }
 
-static inline void free_tio(struct mapped_device *md, struct target_io *tio)
+static void free_tio(struct mapped_device *md, struct dm_target_io *tio)
 {
        mempool_free(tio, md->tio_pool);
 }
@@ -498,7 +496,7 @@ static void dec_pending(struct dm_io *io, int error)
 static int clone_endio(struct bio *bio, unsigned int done, int error)
 {
        int r = 0;
-       struct target_io *tio = bio->bi_private;
+       struct dm_target_io *tio = bio->bi_private;
        struct mapped_device *md = tio->io->md;
        dm_endio_fn endio = tio->ti->type->end_io;
 
@@ -558,7 +556,7 @@ static sector_t max_io_len(struct mapped_device *md,
 }
 
 static void __map_bio(struct dm_target *ti, struct bio *clone,
-                     struct target_io *tio)
+                     struct dm_target_io *tio)
 {
        int r;
        sector_t sector;
@@ -672,7 +670,7 @@ static void __clone_and_map(struct clone_info *ci)
        struct bio *clone, *bio = ci->bio;
        struct dm_target *ti = dm_table_find_target(ci->map, ci->sector);
        sector_t len = 0, max = max_io_len(ci->md, ci->sector, ti);
-       struct target_io *tio;
+       struct dm_target_io *tio;
 
        /*
         * Allocate a target io object.
@@ -802,6 +800,15 @@ static int dm_request(request_queue_t *q, struct bio *bio)
        int rw = bio_data_dir(bio);
        struct mapped_device *md = q->queuedata;
 
+       /*
+        * There is no use in forwarding any barrier request since we can't
+        * guarantee it is (or can be) handled by the targets correctly.
+        */
+       if (unlikely(bio_barrier(bio))) {
+               bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+               return 0;
+       }
+
        down_read(&md->io_lock);
 
        disk_stat_inc(dm_disk(md), ios[rw]);
index 2f796b1436b2a6f898fac79f05cf4bee036d04f0..462ee652a89015c94490d6500b3e8f879fd8de46 100644 (file)
 
 #define DM_NAME "device-mapper"
 
-#define DMERR(f, arg...) printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
-#define DMWARN(f, arg...) printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
-#define DMINFO(f, arg...) printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMERR(f, arg...) \
+       printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMERR_LIMIT(f, arg...) \
+       do { \
+               if (printk_ratelimit()) \
+                       printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " \
+                              f "\n", ## arg); \
+       } while (0)
+
+#define DMWARN(f, arg...) \
+       printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMWARN_LIMIT(f, arg...) \
+       do { \
+               if (printk_ratelimit()) \
+                       printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " \
+                              f "\n", ## arg); \
+       } while (0)
+
+#define DMINFO(f, arg...) \
+       printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMINFO_LIMIT(f, arg...) \
+       do { \
+               if (printk_ratelimit()) \
+                       printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f \
+                              "\n", ## arg); \
+       } while (0)
+
 #ifdef CONFIG_DM_DEBUG
-#  define DMDEBUG(f, arg...) printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
+#  define DMDEBUG(f, arg...) \
+       printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
+#  define DMDEBUG_LIMIT(f, arg...) \
+       do { \
+               if (printk_ratelimit()) \
+                       printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX ": " f \
+                              "\n", ## arg); \
+       } while (0)
 #else
 #  define DMDEBUG(f, arg...) do {} while (0)
+#  define DMDEBUG_LIMIT(f, arg...) do {} while (0)
 #endif
 
 #define DMEMIT(x...) sz += ((sz >= maxlen) ? \
index dbc234e3c69f917fb58e7a2f7d26b89dea324b9f..7e052378c47ea6af6c42eec7f134934b6d49d1c0 100644 (file)
@@ -29,7 +29,7 @@
 static struct workqueue_struct *_kcopyd_wq;
 static struct work_struct _kcopyd_work;
 
-static inline void wake(void)
+static void wake(void)
 {
        queue_work(_kcopyd_wq, &_kcopyd_work);
 }
@@ -226,10 +226,7 @@ static LIST_HEAD(_pages_jobs);
 
 static int jobs_init(void)
 {
-       _job_cache = kmem_cache_create("kcopyd-jobs",
-                                      sizeof(struct kcopyd_job),
-                                      __alignof__(struct kcopyd_job),
-                                      0, NULL, NULL);
+       _job_cache = KMEM_CACHE(kcopyd_job, 0);
        if (!_job_cache)
                return -ENOMEM;
 
@@ -258,7 +255,7 @@ static void jobs_exit(void)
  * Functions to push and pop a job onto the head of a given job
  * list.
  */
-static inline struct kcopyd_job *pop(struct list_head *jobs)
+static struct kcopyd_job *pop(struct list_head *jobs)
 {
        struct kcopyd_job *job = NULL;
        unsigned long flags;
@@ -274,7 +271,7 @@ static inline struct kcopyd_job *pop(struct list_head *jobs)
        return job;
 }
 
-static inline void push(struct list_head *jobs, struct kcopyd_job *job)
+static void push(struct list_head *jobs, struct kcopyd_job *job)
 {
        unsigned long flags;
 
index 1c54f3c1cca74fca038b5b4452c9a0504e481e57..33beaa7da085cb487ed3ab47710dec048488df6b 100644 (file)
@@ -5814,7 +5814,7 @@ static __exit void md_exit(void)
        }
 }
 
-module_init(md_init)
+subsys_initcall(md_init);
 module_exit(md_exit)
 
 static int get_ro(char *buffer, struct kernel_param *kp)
index 061375ee6592517cf1796c2ff730b5cefcbc7269..0b66afef2d82009be4f54c34880df588a8a22b61 100644 (file)
@@ -52,6 +52,7 @@
 #include "raid6.h"
 
 #include <linux/raid/bitmap.h>
+#include <linux/async_tx.h>
 
 /*
  * Stripe cache
@@ -80,7 +81,6 @@
 /*
  * The following can be used to debug the driver
  */
-#define RAID5_DEBUG    0
 #define RAID5_PARANOIA 1
 #if RAID5_PARANOIA && defined(CONFIG_SMP)
 # define CHECK_DEVLOCK() assert_spin_locked(&conf->device_lock)
@@ -88,8 +88,7 @@
 # define CHECK_DEVLOCK()
 #endif
 
-#define PRINTK(x...) ((void)(RAID5_DEBUG && printk(x)))
-#if RAID5_DEBUG
+#ifdef DEBUG
 #define inline
 #define __inline__
 #endif
@@ -104,6 +103,23 @@ static inline int raid6_next_disk(int disk, int raid_disks)
        disk++;
        return (disk < raid_disks) ? disk : 0;
 }
+
+static void return_io(struct bio *return_bi)
+{
+       struct bio *bi = return_bi;
+       while (bi) {
+               int bytes = bi->bi_size;
+
+               return_bi = bi->bi_next;
+               bi->bi_next = NULL;
+               bi->bi_size = 0;
+               bi->bi_end_io(bi, bytes,
+                             test_bit(BIO_UPTODATE, &bi->bi_flags)
+                               ? 0 : -EIO);
+               bi = return_bi;
+       }
+}
+
 static void print_raid5_conf (raid5_conf_t *conf);
 
 static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
@@ -125,6 +141,7 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
                        }
                        md_wakeup_thread(conf->mddev->thread);
                } else {
+                       BUG_ON(sh->ops.pending);
                        if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
                                atomic_dec(&conf->preread_active_stripes);
                                if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
@@ -152,7 +169,8 @@ static void release_stripe(struct stripe_head *sh)
 
 static inline void remove_hash(struct stripe_head *sh)
 {
-       PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
+       pr_debug("remove_hash(), stripe %llu\n",
+               (unsigned long long)sh->sector);
 
        hlist_del_init(&sh->hash);
 }
@@ -161,7 +179,8 @@ static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
 {
        struct hlist_head *hp = stripe_hash(conf, sh->sector);
 
-       PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
+       pr_debug("insert_hash(), stripe %llu\n",
+               (unsigned long long)sh->sector);
 
        CHECK_DEVLOCK();
        hlist_add_head(&sh->hash, hp);
@@ -224,9 +243,10 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int
 
        BUG_ON(atomic_read(&sh->count) != 0);
        BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
-       
+       BUG_ON(sh->ops.pending || sh->ops.ack || sh->ops.complete);
+
        CHECK_DEVLOCK();
-       PRINTK("init_stripe called, stripe %llu\n", 
+       pr_debug("init_stripe called, stripe %llu\n",
                (unsigned long long)sh->sector);
 
        remove_hash(sh);
@@ -240,11 +260,11 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int
        for (i = sh->disks; i--; ) {
                struct r5dev *dev = &sh->dev[i];
 
-               if (dev->toread || dev->towrite || dev->written ||
+               if (dev->toread || dev->read || dev->towrite || dev->written ||
                    test_bit(R5_LOCKED, &dev->flags)) {
-                       printk("sector=%llx i=%d %p %p %p %d\n",
+                       printk(KERN_ERR "sector=%llx i=%d %p %p %p %p %d\n",
                               (unsigned long long)sh->sector, i, dev->toread,
-                              dev->towrite, dev->written,
+                              dev->read, dev->towrite, dev->written,
                               test_bit(R5_LOCKED, &dev->flags));
                        BUG();
                }
@@ -260,11 +280,11 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector, in
        struct hlist_node *hn;
 
        CHECK_DEVLOCK();
-       PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
+       pr_debug("__find_stripe, sector %llu\n", (unsigned long long)sector);
        hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
                if (sh->sector == sector && sh->disks == disks)
                        return sh;
-       PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
+       pr_debug("__stripe %llu not in cache\n", (unsigned long long)sector);
        return NULL;
 }
 
@@ -276,7 +296,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
 {
        struct stripe_head *sh;
 
-       PRINTK("get_stripe, sector %llu\n", (unsigned long long)sector);
+       pr_debug("get_stripe, sector %llu\n", (unsigned long long)sector);
 
        spin_lock_irq(&conf->device_lock);
 
@@ -324,407 +344,980 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
        return sh;
 }
 
-static int grow_one_stripe(raid5_conf_t *conf)
+/* test_and_ack_op() ensures that we only dequeue an operation once */
+#define test_and_ack_op(op, pend) \
+do {                                                   \
+       if (test_bit(op, &sh->ops.pending) &&           \
+               !test_bit(op, &sh->ops.complete)) {     \
+               if (test_and_set_bit(op, &sh->ops.ack)) \
+                       clear_bit(op, &pend);           \
+               else                                    \
+                       ack++;                          \
+       } else                                          \
+               clear_bit(op, &pend);                   \
+} while (0)
+
+/* find new work to run, do not resubmit work that is already
+ * in flight
+ */
+static unsigned long get_stripe_work(struct stripe_head *sh)
 {
-       struct stripe_head *sh;
-       sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
-       if (!sh)
-               return 0;
-       memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
-       sh->raid_conf = conf;
-       spin_lock_init(&sh->lock);
+       unsigned long pending;
+       int ack = 0;
 
-       if (grow_buffers(sh, conf->raid_disks)) {
-               shrink_buffers(sh, conf->raid_disks);
-               kmem_cache_free(conf->slab_cache, sh);
-               return 0;
-       }
-       sh->disks = conf->raid_disks;
-       /* we just created an active stripe so... */
-       atomic_set(&sh->count, 1);
-       atomic_inc(&conf->active_stripes);
-       INIT_LIST_HEAD(&sh->lru);
-       release_stripe(sh);
-       return 1;
-}
+       pending = sh->ops.pending;
 
-static int grow_stripes(raid5_conf_t *conf, int num)
-{
-       struct kmem_cache *sc;
-       int devs = conf->raid_disks;
+       test_and_ack_op(STRIPE_OP_BIOFILL, pending);
+       test_and_ack_op(STRIPE_OP_COMPUTE_BLK, pending);
+       test_and_ack_op(STRIPE_OP_PREXOR, pending);
+       test_and_ack_op(STRIPE_OP_BIODRAIN, pending);
+       test_and_ack_op(STRIPE_OP_POSTXOR, pending);
+       test_and_ack_op(STRIPE_OP_CHECK, pending);
+       if (test_and_clear_bit(STRIPE_OP_IO, &sh->ops.pending))
+               ack++;
 
-       sprintf(conf->cache_name[0], "raid5-%s", mdname(conf->mddev));
-       sprintf(conf->cache_name[1], "raid5-%s-alt", mdname(conf->mddev));
-       conf->active_name = 0;
-       sc = kmem_cache_create(conf->cache_name[conf->active_name],
-                              sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
-                              0, 0, NULL, NULL);
-       if (!sc)
-               return 1;
-       conf->slab_cache = sc;
-       conf->pool_size = devs;
-       while (num--)
-               if (!grow_one_stripe(conf))
-                       return 1;
-       return 0;
+       sh->ops.count -= ack;
+       BUG_ON(sh->ops.count < 0);
+
+       return pending;
 }
 
-#ifdef CONFIG_MD_RAID5_RESHAPE
-static int resize_stripes(raid5_conf_t *conf, int newsize)
+static int
+raid5_end_read_request(struct bio *bi, unsigned int bytes_done, int error);
+static int
+raid5_end_write_request (struct bio *bi, unsigned int bytes_done, int error);
+
+static void ops_run_io(struct stripe_head *sh)
 {
-       /* Make all the stripes able to hold 'newsize' devices.
-        * New slots in each stripe get 'page' set to a new page.
-        *
-        * This happens in stages:
-        * 1/ create a new kmem_cache and allocate the required number of
-        *    stripe_heads.
-        * 2/ gather all the old stripe_heads and tranfer the pages across
-        *    to the new stripe_heads.  This will have the side effect of
-        *    freezing the array as once all stripe_heads have been collected,
-        *    no IO will be possible.  Old stripe heads are freed once their
-        *    pages have been transferred over, and the old kmem_cache is
-        *    freed when all stripes are done.
-        * 3/ reallocate conf->disks to be suitable bigger.  If this fails,
-        *    we simple return a failre status - no need to clean anything up.
-        * 4/ allocate new pages for the new slots in the new stripe_heads.
-        *    If this fails, we don't bother trying the shrink the
-        *    stripe_heads down again, we just leave them as they are.
-        *    As each stripe_head is processed the new one is released into
-        *    active service.
-        *
-        * Once step2 is started, we cannot afford to wait for a write,
-        * so we use GFP_NOIO allocations.
-        */
-       struct stripe_head *osh, *nsh;
-       LIST_HEAD(newstripes);
-       struct disk_info *ndisks;
-       int err = 0;
-       struct kmem_cache *sc;
-       int i;
+       raid5_conf_t *conf = sh->raid_conf;
+       int i, disks = sh->disks;
 
-       if (newsize <= conf->pool_size)
-               return 0; /* never bother to shrink */
+       might_sleep();
 
-       md_allow_write(conf->mddev);
+       for (i = disks; i--; ) {
+               int rw;
+               struct bio *bi;
+               mdk_rdev_t *rdev;
+               if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
+                       rw = WRITE;
+               else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
+                       rw = READ;
+               else
+                       continue;
 
-       /* Step 1 */
-       sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
-                              sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
-                              0, 0, NULL, NULL);
-       if (!sc)
-               return -ENOMEM;
+               bi = &sh->dev[i].req;
 
-       for (i = conf->max_nr_stripes; i; i--) {
-               nsh = kmem_cache_alloc(sc, GFP_KERNEL);
-               if (!nsh)
-                       break;
+               bi->bi_rw = rw;
+               if (rw == WRITE)
+                       bi->bi_end_io = raid5_end_write_request;
+               else
+                       bi->bi_end_io = raid5_end_read_request;
 
-               memset(nsh, 0, sizeof(*nsh) + (newsize-1)*sizeof(struct r5dev));
+               rcu_read_lock();
+               rdev = rcu_dereference(conf->disks[i].rdev);
+               if (rdev && test_bit(Faulty, &rdev->flags))
+                       rdev = NULL;
+               if (rdev)
+                       atomic_inc(&rdev->nr_pending);
+               rcu_read_unlock();
 
-               nsh->raid_conf = conf;
-               spin_lock_init(&nsh->lock);
+               if (rdev) {
+                       if (test_bit(STRIPE_SYNCING, &sh->state) ||
+                               test_bit(STRIPE_EXPAND_SOURCE, &sh->state) ||
+                               test_bit(STRIPE_EXPAND_READY, &sh->state))
+                               md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 
-               list_add(&nsh->lru, &newstripes);
-       }
-       if (i) {
-               /* didn't get enough, give up */
-               while (!list_empty(&newstripes)) {
-                       nsh = list_entry(newstripes.next, struct stripe_head, lru);
-                       list_del(&nsh->lru);
-                       kmem_cache_free(sc, nsh);
+                       bi->bi_bdev = rdev->bdev;
+                       pr_debug("%s: for %llu schedule op %ld on disc %d\n",
+                               __FUNCTION__, (unsigned long long)sh->sector,
+                               bi->bi_rw, i);
+                       atomic_inc(&sh->count);
+                       bi->bi_sector = sh->sector + rdev->data_offset;
+                       bi->bi_flags = 1 << BIO_UPTODATE;
+                       bi->bi_vcnt = 1;
+                       bi->bi_max_vecs = 1;
+                       bi->bi_idx = 0;
+                       bi->bi_io_vec = &sh->dev[i].vec;
+                       bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
+                       bi->bi_io_vec[0].bv_offset = 0;
+                       bi->bi_size = STRIPE_SIZE;
+                       bi->bi_next = NULL;
+                       if (rw == WRITE &&
+                           test_bit(R5_ReWrite, &sh->dev[i].flags))
+                               atomic_add(STRIPE_SECTORS,
+                                       &rdev->corrected_errors);
+                       generic_make_request(bi);
+               } else {
+                       if (rw == WRITE)
+                               set_bit(STRIPE_DEGRADED, &sh->state);
+                       pr_debug("skip op %ld on disc %d for sector %llu\n",
+                               bi->bi_rw, i, (unsigned long long)sh->sector);
+                       clear_bit(R5_LOCKED, &sh->dev[i].flags);
+                       set_bit(STRIPE_HANDLE, &sh->state);
                }
-               kmem_cache_destroy(sc);
-               return -ENOMEM;
-       }
-       /* Step 2 - Must use GFP_NOIO now.
-        * OK, we have enough stripes, start collecting inactive
-        * stripes and copying them over
-        */
-       list_for_each_entry(nsh, &newstripes, lru) {
-               spin_lock_irq(&conf->device_lock);
-               wait_event_lock_irq(conf->wait_for_stripe,
-                                   !list_empty(&conf->inactive_list),
-                                   conf->device_lock,
-                                   unplug_slaves(conf->mddev)
-                       );
-               osh = get_free_stripe(conf);
-               spin_unlock_irq(&conf->device_lock);
-               atomic_set(&nsh->count, 1);
-               for(i=0; i<conf->pool_size; i++)
-                       nsh->dev[i].page = osh->dev[i].page;
-               for( ; i<newsize; i++)
-                       nsh->dev[i].page = NULL;
-               kmem_cache_free(conf->slab_cache, osh);
        }
-       kmem_cache_destroy(conf->slab_cache);
+}
 
-       /* Step 3.
-        * At this point, we are holding all the stripes so the array
-        * is completely stalled, so now is a good time to resize
-        * conf->disks.
-        */
-       ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO);
-       if (ndisks) {
-               for (i=0; i<conf->raid_disks; i++)
-                       ndisks[i] = conf->disks[i];
-               kfree(conf->disks);
-               conf->disks = ndisks;
-       } else
-               err = -ENOMEM;
+static struct dma_async_tx_descriptor *
+async_copy_data(int frombio, struct bio *bio, struct page *page,
+       sector_t sector, struct dma_async_tx_descriptor *tx)
+{
+       struct bio_vec *bvl;
+       struct page *bio_page;
+       int i;
+       int page_offset;
 
-       /* Step 4, return new stripes to service */
-       while(!list_empty(&newstripes)) {
-               nsh = list_entry(newstripes.next, struct stripe_head, lru);
-               list_del_init(&nsh->lru);
-               for (i=conf->raid_disks; i < newsize; i++)
-                       if (nsh->dev[i].page == NULL) {
-                               struct page *p = alloc_page(GFP_NOIO);
-                               nsh->dev[i].page = p;
-                               if (!p)
-                                       err = -ENOMEM;
-                       }
-               release_stripe(nsh);
+       if (bio->bi_sector >= sector)
+               page_offset = (signed)(bio->bi_sector - sector) * 512;
+       else
+               page_offset = (signed)(sector - bio->bi_sector) * -512;
+       bio_for_each_segment(bvl, bio, i) {
+               int len = bio_iovec_idx(bio, i)->bv_len;
+               int clen;
+               int b_offset = 0;
+
+               if (page_offset < 0) {
+                       b_offset = -page_offset;
+                       page_offset += b_offset;
+                       len -= b_offset;
+               }
+
+               if (len > 0 && page_offset + len > STRIPE_SIZE)
+                       clen = STRIPE_SIZE - page_offset;
+               else
+                       clen = len;
+
+               if (clen > 0) {
+                       b_offset += bio_iovec_idx(bio, i)->bv_offset;
+                       bio_page = bio_iovec_idx(bio, i)->bv_page;
+                       if (frombio)
+                               tx = async_memcpy(page, bio_page, page_offset,
+                                       b_offset, clen,
+                                       ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_SRC,
+                                       tx, NULL, NULL);
+                       else
+                               tx = async_memcpy(bio_page, page, b_offset,
+                                       page_offset, clen,
+                                       ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_DST,
+                                       tx, NULL, NULL);
+               }
+               if (clen < len) /* hit end of page */
+                       break;
+               page_offset +=  len;
        }
-       /* critical section pass, GFP_NOIO no longer needed */
 
-       conf->slab_cache = sc;
-       conf->active_name = 1-conf->active_name;
-       conf->pool_size = newsize;
-       return err;
+       return tx;
 }
-#endif
 
-static int drop_one_stripe(raid5_conf_t *conf)
+static void ops_complete_biofill(void *stripe_head_ref)
 {
-       struct stripe_head *sh;
+       struct stripe_head *sh = stripe_head_ref;
+       struct bio *return_bi = NULL;
+       raid5_conf_t *conf = sh->raid_conf;
+       int i, more_to_read = 0;
 
-       spin_lock_irq(&conf->device_lock);
-       sh = get_free_stripe(conf);
-       spin_unlock_irq(&conf->device_lock);
-       if (!sh)
-               return 0;
-       BUG_ON(atomic_read(&sh->count));
-       shrink_buffers(sh, conf->pool_size);
-       kmem_cache_free(conf->slab_cache, sh);
-       atomic_dec(&conf->active_stripes);
-       return 1;
-}
+       pr_debug("%s: stripe %llu\n", __FUNCTION__,
+               (unsigned long long)sh->sector);
 
-static void shrink_stripes(raid5_conf_t *conf)
-{
-       while (drop_one_stripe(conf))
-               ;
+       /* clear completed biofills */
+       for (i = sh->disks; i--; ) {
+               struct r5dev *dev = &sh->dev[i];
+               /* check if this stripe has new incoming reads */
+               if (dev->toread)
+                       more_to_read++;
+
+               /* acknowledge completion of a biofill operation */
+               /* and check if we need to reply to a read request
+               */
+               if (test_bit(R5_Wantfill, &dev->flags) && !dev->toread) {
+                       struct bio *rbi, *rbi2;
+                       clear_bit(R5_Wantfill, &dev->flags);
 
-       if (conf->slab_cache)
-               kmem_cache_destroy(conf->slab_cache);
-       conf->slab_cache = NULL;
+                       /* The access to dev->read is outside of the
+                        * spin_lock_irq(&conf->device_lock), but is protected
+                        * by the STRIPE_OP_BIOFILL pending bit
+                        */
+                       BUG_ON(!dev->read);
+                       rbi = dev->read;
+                       dev->read = NULL;
+                       while (rbi && rbi->bi_sector <
+                               dev->sector + STRIPE_SECTORS) {
+                               rbi2 = r5_next_bio(rbi, dev->sector);
+                               spin_lock_irq(&conf->device_lock);
+                               if (--rbi->bi_phys_segments == 0) {
+                                       rbi->bi_next = return_bi;
+                                       return_bi = rbi;
+                               }
+                               spin_unlock_irq(&conf->device_lock);
+                               rbi = rbi2;
+                       }
+               }
+       }
+       clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack);
+       clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending);
+
+       return_io(return_bi);
+
+       if (more_to_read)
+               set_bit(STRIPE_HANDLE, &sh->state);
+       release_stripe(sh);
 }
 
-static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
-                                  int error)
+static void ops_run_biofill(struct stripe_head *sh)
 {
-       struct stripe_head *sh = bi->bi_private;
+       struct dma_async_tx_descriptor *tx = NULL;
        raid5_conf_t *conf = sh->raid_conf;
-       int disks = sh->disks, i;
-       int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
-       char b[BDEVNAME_SIZE];
-       mdk_rdev_t *rdev;
-
-       if (bi->bi_size)
-               return 1;
+       int i;
 
-       for (i=0 ; i<disks; i++)
-               if (bi == &sh->dev[i].req)
-                       break;
+       pr_debug("%s: stripe %llu\n", __FUNCTION__,
+               (unsigned long long)sh->sector);
 
-       PRINTK("end_read_request %llu/%d, count: %d, uptodate %d.\n", 
-               (unsigned long long)sh->sector, i, atomic_read(&sh->count), 
-               uptodate);
-       if (i == disks) {
-               BUG();
-               return 0;
+       for (i = sh->disks; i--; ) {
+               struct r5dev *dev = &sh->dev[i];
+               if (test_bit(R5_Wantfill, &dev->flags)) {
+                       struct bio *rbi;
+                       spin_lock_irq(&conf->device_lock);
+                       dev->read = rbi = dev->toread;
+                       dev->toread = NULL;
+                       spin_unlock_irq(&conf->device_lock);
+                       while (rbi && rbi->bi_sector <
+                               dev->sector + STRIPE_SECTORS) {
+                               tx = async_copy_data(0, rbi, dev->page,
+                                       dev->sector, tx);
+                               rbi = r5_next_bio(rbi, dev->sector);
+                       }
+               }
        }
 
-       if (uptodate) {
-               set_bit(R5_UPTODATE, &sh->dev[i].flags);
-               if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-                       rdev = conf->disks[i].rdev;
-                       printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n",
-                              mdname(conf->mddev), STRIPE_SECTORS,
-                              (unsigned long long)sh->sector + rdev->data_offset,
-                              bdevname(rdev->bdev, b));
-                       clear_bit(R5_ReadError, &sh->dev[i].flags);
-                       clear_bit(R5_ReWrite, &sh->dev[i].flags);
-               }
-               if (atomic_read(&conf->disks[i].rdev->read_errors))
-                       atomic_set(&conf->disks[i].rdev->read_errors, 0);
-       } else {
-               const char *bdn = bdevname(conf->disks[i].rdev->bdev, b);
-               int retry = 0;
-               rdev = conf->disks[i].rdev;
+       atomic_inc(&sh->count);
+       async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
+               ops_complete_biofill, sh);
+}
 
-               clear_bit(R5_UPTODATE, &sh->dev[i].flags);
-               atomic_inc(&rdev->read_errors);
-               if (conf->mddev->degraded)
-                       printk(KERN_WARNING "raid5:%s: read error not correctable (sector %llu on %s).\n",
-                              mdname(conf->mddev),
-                              (unsigned long long)sh->sector + rdev->data_offset,
-                              bdn);
-               else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
-                       /* Oh, no!!! */
-                       printk(KERN_WARNING "raid5:%s: read error NOT corrected!! (sector %llu on %s).\n",
-                              mdname(conf->mddev),
-                              (unsigned long long)sh->sector + rdev->data_offset,
-                              bdn);
-               else if (atomic_read(&rdev->read_errors)
-                        > conf->max_nr_stripes)
-                       printk(KERN_WARNING
-                              "raid5:%s: Too many read errors, failing device %s.\n",
-                              mdname(conf->mddev), bdn);
-               else
-                       retry = 1;
-               if (retry)
-                       set_bit(R5_ReadError, &sh->dev[i].flags);
-               else {
-                       clear_bit(R5_ReadError, &sh->dev[i].flags);
-                       clear_bit(R5_ReWrite, &sh->dev[i].flags);
-                       md_error(conf->mddev, rdev);
-               }
-       }
-       rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
-       clear_bit(R5_LOCKED, &sh->dev[i].flags);
+static void ops_complete_compute5(void *stripe_head_ref)
+{
+       struct stripe_head *sh = stripe_head_ref;
+       int target = sh->ops.target;
+       struct r5dev *tgt = &sh->dev[target];
+
+       pr_debug("%s: stripe %llu\n", __FUNCTION__,
+               (unsigned long long)sh->sector);
+
+       set_bit(R5_UPTODATE, &tgt->flags);
+       BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
+       clear_bit(R5_Wantcompute, &tgt->flags);
+       set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
        set_bit(STRIPE_HANDLE, &sh->state);
        release_stripe(sh);
-       return 0;
 }
 
-static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
-                                   int error)
+static struct dma_async_tx_descriptor *
+ops_run_compute5(struct stripe_head *sh, unsigned long pending)
 {
-       struct stripe_head *sh = bi->bi_private;
-       raid5_conf_t *conf = sh->raid_conf;
-       int disks = sh->disks, i;
-       int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
+       /* kernel stack size limits the total number of disks */
+       int disks = sh->disks;
+       struct page *xor_srcs[disks];
+       int target = sh->ops.target;
+       struct r5dev *tgt = &sh->dev[target];
+       struct page *xor_dest = tgt->page;
+       int count = 0;
+       struct dma_async_tx_descriptor *tx;
+       int i;
 
-       if (bi->bi_size)
-               return 1;
+       pr_debug("%s: stripe %llu block: %d\n",
+               __FUNCTION__, (unsigned long long)sh->sector, target);
+       BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
 
-       for (i=0 ; i<disks; i++)
-               if (bi == &sh->dev[i].req)
-                       break;
+       for (i = disks; i--; )
+               if (i != target)
+                       xor_srcs[count++] = sh->dev[i].page;
 
-       PRINTK("end_write_request %llu/%d, count %d, uptodate: %d.\n", 
-               (unsigned long long)sh->sector, i, atomic_read(&sh->count),
-               uptodate);
-       if (i == disks) {
-               BUG();
-               return 0;
-       }
+       atomic_inc(&sh->count);
 
-       if (!uptodate)
-               md_error(conf->mddev, conf->disks[i].rdev);
+       if (unlikely(count == 1))
+               tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
+                       0, NULL, ops_complete_compute5, sh);
+       else
+               tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+                       ASYNC_TX_XOR_ZERO_DST, NULL,
+                       ops_complete_compute5, sh);
 
-       rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
-       
-       clear_bit(R5_LOCKED, &sh->dev[i].flags);
-       set_bit(STRIPE_HANDLE, &sh->state);
-       release_stripe(sh);
-       return 0;
+       /* ack now if postxor is not set to be run */
+       if (tx && !test_bit(STRIPE_OP_POSTXOR, &pending))
+               async_tx_ack(tx);
+
+       return tx;
 }
 
+static void ops_complete_prexor(void *stripe_head_ref)
+{
+       struct stripe_head *sh = stripe_head_ref;
 
-static sector_t compute_blocknr(struct stripe_head *sh, int i);
-       
-static void raid5_build_block (struct stripe_head *sh, int i)
+       pr_debug("%s: stripe %llu\n", __FUNCTION__,
+               (unsigned long long)sh->sector);
+
+       set_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
+}
+
+static struct dma_async_tx_descriptor *
+ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
 {
-       struct r5dev *dev = &sh->dev[i];
+       /* kernel stack size limits the total number of disks */
+       int disks = sh->disks;
+       struct page *xor_srcs[disks];
+       int count = 0, pd_idx = sh->pd_idx, i;
 
-       bio_init(&dev->req);
-       dev->req.bi_io_vec = &dev->vec;
-       dev->req.bi_vcnt++;
-       dev->req.bi_max_vecs++;
-       dev->vec.bv_page = dev->page;
-       dev->vec.bv_len = STRIPE_SIZE;
-       dev->vec.bv_offset = 0;
+       /* existing parity data subtracted */
+       struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
 
-       dev->req.bi_sector = sh->sector;
-       dev->req.bi_private = sh;
+       pr_debug("%s: stripe %llu\n", __FUNCTION__,
+               (unsigned long long)sh->sector);
 
-       dev->flags = 0;
-       dev->sector = compute_blocknr(sh, i);
+       for (i = disks; i--; ) {
+               struct r5dev *dev = &sh->dev[i];
+               /* Only process blocks that are known to be uptodate */
+               if (dev->towrite && test_bit(R5_Wantprexor, &dev->flags))
+                       xor_srcs[count++] = dev->page;
+       }
+
+       tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+               ASYNC_TX_DEP_ACK | ASYNC_TX_XOR_DROP_DST, tx,
+               ops_complete_prexor, sh);
+
+       return tx;
 }
 
-static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+static struct dma_async_tx_descriptor *
+ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
 {
-       char b[BDEVNAME_SIZE];
-       raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
-       PRINTK("raid5: error called\n");
+       int disks = sh->disks;
+       int pd_idx = sh->pd_idx, i;
 
-       if (!test_bit(Faulty, &rdev->flags)) {
-               set_bit(MD_CHANGE_DEVS, &mddev->flags);
-               if (test_and_clear_bit(In_sync, &rdev->flags)) {
-                       unsigned long flags;
-                       spin_lock_irqsave(&conf->device_lock, flags);
-                       mddev->degraded++;
-                       spin_unlock_irqrestore(&conf->device_lock, flags);
-                       /*
-                        * if recovery was running, make sure it aborts.
-                        */
-                       set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+       /* check if prexor is active which means only process blocks
+        * that are part of a read-modify-write (Wantprexor)
+        */
+       int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+
+       pr_debug("%s: stripe %llu\n", __FUNCTION__,
+               (unsigned long long)sh->sector);
+
+       for (i = disks; i--; ) {
+               struct r5dev *dev = &sh->dev[i];
+               struct bio *chosen;
+               int towrite;
+
+               towrite = 0;
+               if (prexor) { /* rmw */
+                       if (dev->towrite &&
+                           test_bit(R5_Wantprexor, &dev->flags))
+                               towrite = 1;
+               } else { /* rcw */
+                       if (i != pd_idx && dev->towrite &&
+                               test_bit(R5_LOCKED, &dev->flags))
+                               towrite = 1;
                }
-               set_bit(Faulty, &rdev->flags);
-               printk (KERN_ALERT
-                       "raid5: Disk failure on %s, disabling device."
-                       " Operation continuing on %d devices\n",
-                       bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded);
+
+               if (towrite) {
+                       struct bio *wbi;
+
+                       spin_lock(&sh->lock);
+                       chosen = dev->towrite;
+                       dev->towrite = NULL;
+                       BUG_ON(dev->written);
+                       wbi = dev->written = chosen;
+                       spin_unlock(&sh->lock);
+
+                       while (wbi && wbi->bi_sector <
+                               dev->sector + STRIPE_SECTORS) {
+                               tx = async_copy_data(1, wbi, dev->page,
+                                       dev->sector, tx);
+                               wbi = r5_next_bio(wbi, dev->sector);
+                       }
+               }
+       }
+
+       return tx;
+}
+
+static void ops_complete_postxor(void *stripe_head_ref)
+{
+       struct stripe_head *sh = stripe_head_ref;
+
+       pr_debug("%s: stripe %llu\n", __FUNCTION__,
+               (unsigned long long)sh->sector);
+
+       set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+       set_bit(STRIPE_HANDLE, &sh->state);
+       release_stripe(sh);
+}
+
+static void ops_complete_write(void *stripe_head_ref)
+{
+       struct stripe_head *sh = stripe_head_ref;
+       int disks = sh->disks, i, pd_idx = sh->pd_idx;
+
+       pr_debug("%s: stripe %llu\n", __FUNCTION__,
+               (unsigned long long)sh->sector);
+
+       for (i = disks; i--; ) {
+               struct r5dev *dev = &sh->dev[i];
+               if (dev->written || i == pd_idx)
+                       set_bit(R5_UPTODATE, &dev->flags);
        }
+
+       set_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
+       set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+
+       set_bit(STRIPE_HANDLE, &sh->state);
+       release_stripe(sh);
 }
 
-/*
- * Input: a 'big' sector number,
- * Output: index of the data and parity disk, and the sector # in them.
- */
-static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
-                       unsigned int data_disks, unsigned int * dd_idx,
-                       unsigned int * pd_idx, raid5_conf_t *conf)
+static void
+ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
 {
-       long stripe;
-       unsigned long chunk_number;
-       unsigned int chunk_offset;
-       sector_t new_sector;
-       int sectors_per_chunk = conf->chunk_size >> 9;
+       /* kernel stack size limits the total number of disks */
+       int disks = sh->disks;
+       struct page *xor_srcs[disks];
 
-       /* First compute the information on this sector */
+       int count = 0, pd_idx = sh->pd_idx, i;
+       struct page *xor_dest;
+       int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+       unsigned long flags;
+       dma_async_tx_callback callback;
 
-       /*
-        * Compute the chunk number and the sector offset inside the chunk
-        */
-       chunk_offset = sector_div(r_sector, sectors_per_chunk);
-       chunk_number = r_sector;
-       BUG_ON(r_sector != chunk_number);
+       pr_debug("%s: stripe %llu\n", __FUNCTION__,
+               (unsigned long long)sh->sector);
 
-       /*
-        * Compute the stripe number
+       /* check if prexor is active which means only process blocks
+        * that are part of a read-modify-write (written)
         */
-       stripe = chunk_number / data_disks;
+       if (prexor) {
+               xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+               for (i = disks; i--; ) {
+                       struct r5dev *dev = &sh->dev[i];
+                       if (dev->written)
+                               xor_srcs[count++] = dev->page;
+               }
+       } else {
+               xor_dest = sh->dev[pd_idx].page;
+               for (i = disks; i--; ) {
+                       struct r5dev *dev = &sh->dev[i];
+                       if (i != pd_idx)
+                               xor_srcs[count++] = dev->page;
+               }
+       }
 
-       /*
-        * Compute the data disk and parity disk indexes inside the stripe
-        */
-       *dd_idx = chunk_number % data_disks;
+       /* check whether this postxor is part of a write */
+       callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ?
+               ops_complete_write : ops_complete_postxor;
 
-       /*
-        * Select the parity disk based on the user selected algorithm.
+       /* 1/ if we prexor'd then the dest is reused as a source
+        * 2/ if we did not prexor then we are redoing the parity
+        * set ASYNC_TX_XOR_DROP_DST and ASYNC_TX_XOR_ZERO_DST
+        * for the synchronous xor case
         */
-       switch(conf->level) {
-       case 4:
-               *pd_idx = data_disks;
-               break;
-       case 5:
-               switch (conf->algorithm) {
-               case ALGORITHM_LEFT_ASYMMETRIC:
-                       *pd_idx = data_disks - stripe % raid_disks;
-                       if (*dd_idx >= *pd_idx)
+       flags = ASYNC_TX_DEP_ACK | ASYNC_TX_ACK |
+               (prexor ? ASYNC_TX_XOR_DROP_DST : ASYNC_TX_XOR_ZERO_DST);
+
+       atomic_inc(&sh->count);
+
+       if (unlikely(count == 1)) {
+               flags &= ~(ASYNC_TX_XOR_DROP_DST | ASYNC_TX_XOR_ZERO_DST);
+               tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
+                       flags, tx, callback, sh);
+       } else
+               tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+                       flags, tx, callback, sh);
+}
+
+static void ops_complete_check(void *stripe_head_ref)
+{
+       struct stripe_head *sh = stripe_head_ref;
+       int pd_idx = sh->pd_idx;
+
+       pr_debug("%s: stripe %llu\n", __FUNCTION__,
+               (unsigned long long)sh->sector);
+
+       if (test_and_clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending) &&
+               sh->ops.zero_sum_result == 0)
+               set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+
+       set_bit(STRIPE_OP_CHECK, &sh->ops.complete);
+       set_bit(STRIPE_HANDLE, &sh->state);
+       release_stripe(sh);
+}
+
+static void ops_run_check(struct stripe_head *sh)
+{
+       /* kernel stack size limits the total number of disks */
+       int disks = sh->disks;
+       struct page *xor_srcs[disks];
+       struct dma_async_tx_descriptor *tx;
+
+       int count = 0, pd_idx = sh->pd_idx, i;
+       struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+
+       pr_debug("%s: stripe %llu\n", __FUNCTION__,
+               (unsigned long long)sh->sector);
+
+       for (i = disks; i--; ) {
+               struct r5dev *dev = &sh->dev[i];
+               if (i != pd_idx)
+                       xor_srcs[count++] = dev->page;
+       }
+
+       tx = async_xor_zero_sum(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+               &sh->ops.zero_sum_result, 0, NULL, NULL, NULL);
+
+       if (tx)
+               set_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
+       else
+               clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
+
+       atomic_inc(&sh->count);
+       tx = async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
+               ops_complete_check, sh);
+}
+
+static void raid5_run_ops(struct stripe_head *sh, unsigned long pending)
+{
+       int overlap_clear = 0, i, disks = sh->disks;
+       struct dma_async_tx_descriptor *tx = NULL;
+
+       if (test_bit(STRIPE_OP_BIOFILL, &pending)) {
+               ops_run_biofill(sh);
+               overlap_clear++;
+       }
+
+       if (test_bit(STRIPE_OP_COMPUTE_BLK, &pending))
+               tx = ops_run_compute5(sh, pending);
+
+       if (test_bit(STRIPE_OP_PREXOR, &pending))
+               tx = ops_run_prexor(sh, tx);
+
+       if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
+               tx = ops_run_biodrain(sh, tx);
+               overlap_clear++;
+       }
+
+       if (test_bit(STRIPE_OP_POSTXOR, &pending))
+               ops_run_postxor(sh, tx);
+
+       if (test_bit(STRIPE_OP_CHECK, &pending))
+               ops_run_check(sh);
+
+       if (test_bit(STRIPE_OP_IO, &pending))
+               ops_run_io(sh);
+
+       if (overlap_clear)
+               for (i = disks; i--; ) {
+                       struct r5dev *dev = &sh->dev[i];
+                       if (test_and_clear_bit(R5_Overlap, &dev->flags))
+                               wake_up(&sh->raid_conf->wait_for_overlap);
+               }
+}
+
+static int grow_one_stripe(raid5_conf_t *conf)
+{
+       struct stripe_head *sh;
+       sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
+       if (!sh)
+               return 0;
+       memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
+       sh->raid_conf = conf;
+       spin_lock_init(&sh->lock);
+
+       if (grow_buffers(sh, conf->raid_disks)) {
+               shrink_buffers(sh, conf->raid_disks);
+               kmem_cache_free(conf->slab_cache, sh);
+               return 0;
+       }
+       sh->disks = conf->raid_disks;
+       /* we just created an active stripe so... */
+       atomic_set(&sh->count, 1);
+       atomic_inc(&conf->active_stripes);
+       INIT_LIST_HEAD(&sh->lru);
+       release_stripe(sh);
+       return 1;
+}
+
+static int grow_stripes(raid5_conf_t *conf, int num)
+{
+       struct kmem_cache *sc;
+       int devs = conf->raid_disks;
+
+       sprintf(conf->cache_name[0], "raid5-%s", mdname(conf->mddev));
+       sprintf(conf->cache_name[1], "raid5-%s-alt", mdname(conf->mddev));
+       conf->active_name = 0;
+       sc = kmem_cache_create(conf->cache_name[conf->active_name],
+                              sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
+                              0, 0, NULL, NULL);
+       if (!sc)
+               return 1;
+       conf->slab_cache = sc;
+       conf->pool_size = devs;
+       while (num--)
+               if (!grow_one_stripe(conf))
+                       return 1;
+       return 0;
+}
+
+#ifdef CONFIG_MD_RAID5_RESHAPE
+static int resize_stripes(raid5_conf_t *conf, int newsize)
+{
+       /* Make all the stripes able to hold 'newsize' devices.
+        * New slots in each stripe get 'page' set to a new page.
+        *
+        * This happens in stages:
+        * 1/ create a new kmem_cache and allocate the required number of
+        *    stripe_heads.
+        * 2/ gather all the old stripe_heads and tranfer the pages across
+        *    to the new stripe_heads.  This will have the side effect of
+        *    freezing the array as once all stripe_heads have been collected,
+        *    no IO will be possible.  Old stripe heads are freed once their
+        *    pages have been transferred over, and the old kmem_cache is
+        *    freed when all stripes are done.
+        * 3/ reallocate conf->disks to be suitable bigger.  If this fails,
+        *    we simple return a failre status - no need to clean anything up.
+        * 4/ allocate new pages for the new slots in the new stripe_heads.
+        *    If this fails, we don't bother trying the shrink the
+        *    stripe_heads down again, we just leave them as they are.
+        *    As each stripe_head is processed the new one is released into
+        *    active service.
+        *
+        * Once step2 is started, we cannot afford to wait for a write,
+        * so we use GFP_NOIO allocations.
+        */
+       struct stripe_head *osh, *nsh;
+       LIST_HEAD(newstripes);
+       struct disk_info *ndisks;
+       int err = 0;
+       struct kmem_cache *sc;
+       int i;
+
+       if (newsize <= conf->pool_size)
+               return 0; /* never bother to shrink */
+
+       md_allow_write(conf->mddev);
+
+       /* Step 1 */
+       sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
+                              sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
+                              0, 0, NULL, NULL);
+       if (!sc)
+               return -ENOMEM;
+
+       for (i = conf->max_nr_stripes; i; i--) {
+               nsh = kmem_cache_alloc(sc, GFP_KERNEL);
+               if (!nsh)
+                       break;
+
+               memset(nsh, 0, sizeof(*nsh) + (newsize-1)*sizeof(struct r5dev));
+
+               nsh->raid_conf = conf;
+               spin_lock_init(&nsh->lock);
+
+               list_add(&nsh->lru, &newstripes);
+       }
+       if (i) {
+               /* didn't get enough, give up */
+               while (!list_empty(&newstripes)) {
+                       nsh = list_entry(newstripes.next, struct stripe_head, lru);
+                       list_del(&nsh->lru);
+                       kmem_cache_free(sc, nsh);
+               }
+               kmem_cache_destroy(sc);
+               return -ENOMEM;
+       }
+       /* Step 2 - Must use GFP_NOIO now.
+        * OK, we have enough stripes, start collecting inactive
+        * stripes and copying them over
+        */
+       list_for_each_entry(nsh, &newstripes, lru) {
+               spin_lock_irq(&conf->device_lock);
+               wait_event_lock_irq(conf->wait_for_stripe,
+                                   !list_empty(&conf->inactive_list),
+                                   conf->device_lock,
+                                   unplug_slaves(conf->mddev)
+                       );
+               osh = get_free_stripe(conf);
+               spin_unlock_irq(&conf->device_lock);
+               atomic_set(&nsh->count, 1);
+               for(i=0; i<conf->pool_size; i++)
+                       nsh->dev[i].page = osh->dev[i].page;
+               for( ; i<newsize; i++)
+                       nsh->dev[i].page = NULL;
+               kmem_cache_free(conf->slab_cache, osh);
+       }
+       kmem_cache_destroy(conf->slab_cache);
+
+       /* Step 3.
+        * At this point, we are holding all the stripes so the array
+        * is completely stalled, so now is a good time to resize
+        * conf->disks.
+        */
+       ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO);
+       if (ndisks) {
+               for (i=0; i<conf->raid_disks; i++)
+                       ndisks[i] = conf->disks[i];
+               kfree(conf->disks);
+               conf->disks = ndisks;
+       } else
+               err = -ENOMEM;
+
+       /* Step 4, return new stripes to service */
+       while(!list_empty(&newstripes)) {
+               nsh = list_entry(newstripes.next, struct stripe_head, lru);
+               list_del_init(&nsh->lru);
+               for (i=conf->raid_disks; i < newsize; i++)
+                       if (nsh->dev[i].page == NULL) {
+                               struct page *p = alloc_page(GFP_NOIO);
+                               nsh->dev[i].page = p;
+                               if (!p)
+                                       err = -ENOMEM;
+                       }
+               release_stripe(nsh);
+       }
+       /* critical section pass, GFP_NOIO no longer needed */
+
+       conf->slab_cache = sc;
+       conf->active_name = 1-conf->active_name;
+       conf->pool_size = newsize;
+       return err;
+}
+#endif
+
+static int drop_one_stripe(raid5_conf_t *conf)
+{
+       struct stripe_head *sh;
+
+       spin_lock_irq(&conf->device_lock);
+       sh = get_free_stripe(conf);
+       spin_unlock_irq(&conf->device_lock);
+       if (!sh)
+               return 0;
+       BUG_ON(atomic_read(&sh->count));
+       shrink_buffers(sh, conf->pool_size);
+       kmem_cache_free(conf->slab_cache, sh);
+       atomic_dec(&conf->active_stripes);
+       return 1;
+}
+
+static void shrink_stripes(raid5_conf_t *conf)
+{
+       while (drop_one_stripe(conf))
+               ;
+
+       if (conf->slab_cache)
+               kmem_cache_destroy(conf->slab_cache);
+       conf->slab_cache = NULL;
+}
+
+static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
+                                  int error)
+{
+       struct stripe_head *sh = bi->bi_private;
+       raid5_conf_t *conf = sh->raid_conf;
+       int disks = sh->disks, i;
+       int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
+       char b[BDEVNAME_SIZE];
+       mdk_rdev_t *rdev;
+
+       if (bi->bi_size)
+               return 1;
+
+       for (i=0 ; i<disks; i++)
+               if (bi == &sh->dev[i].req)
+                       break;
+
+       pr_debug("end_read_request %llu/%d, count: %d, uptodate %d.\n",
+               (unsigned long long)sh->sector, i, atomic_read(&sh->count),
+               uptodate);
+       if (i == disks) {
+               BUG();
+               return 0;
+       }
+
+       if (uptodate) {
+               set_bit(R5_UPTODATE, &sh->dev[i].flags);
+               if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+                       rdev = conf->disks[i].rdev;
+                       printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n",
+                              mdname(conf->mddev), STRIPE_SECTORS,
+                              (unsigned long long)sh->sector + rdev->data_offset,
+                              bdevname(rdev->bdev, b));
+                       clear_bit(R5_ReadError, &sh->dev[i].flags);
+                       clear_bit(R5_ReWrite, &sh->dev[i].flags);
+               }
+               if (atomic_read(&conf->disks[i].rdev->read_errors))
+                       atomic_set(&conf->disks[i].rdev->read_errors, 0);
+       } else {
+               const char *bdn = bdevname(conf->disks[i].rdev->bdev, b);
+               int retry = 0;
+               rdev = conf->disks[i].rdev;
+
+               clear_bit(R5_UPTODATE, &sh->dev[i].flags);
+               atomic_inc(&rdev->read_errors);
+               if (conf->mddev->degraded)
+                       printk(KERN_WARNING "raid5:%s: read error not correctable (sector %llu on %s).\n",
+                              mdname(conf->mddev),
+                              (unsigned long long)sh->sector + rdev->data_offset,
+                              bdn);
+               else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
+                       /* Oh, no!!! */
+                       printk(KERN_WARNING "raid5:%s: read error NOT corrected!! (sector %llu on %s).\n",
+                              mdname(conf->mddev),
+                              (unsigned long long)sh->sector + rdev->data_offset,
+                              bdn);
+               else if (atomic_read(&rdev->read_errors)
+                        > conf->max_nr_stripes)
+                       printk(KERN_WARNING
+                              "raid5:%s: Too many read errors, failing device %s.\n",
+                              mdname(conf->mddev), bdn);
+               else
+                       retry = 1;
+               if (retry)
+                       set_bit(R5_ReadError, &sh->dev[i].flags);
+               else {
+                       clear_bit(R5_ReadError, &sh->dev[i].flags);
+                       clear_bit(R5_ReWrite, &sh->dev[i].flags);
+                       md_error(conf->mddev, rdev);
+               }
+       }
+       rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
+       clear_bit(R5_LOCKED, &sh->dev[i].flags);
+       set_bit(STRIPE_HANDLE, &sh->state);
+       release_stripe(sh);
+       return 0;
+}
+
+static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
+                                   int error)
+{
+       struct stripe_head *sh = bi->bi_private;
+       raid5_conf_t *conf = sh->raid_conf;
+       int disks = sh->disks, i;
+       int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
+
+       if (bi->bi_size)
+               return 1;
+
+       for (i=0 ; i<disks; i++)
+               if (bi == &sh->dev[i].req)
+                       break;
+
+       pr_debug("end_write_request %llu/%d, count %d, uptodate: %d.\n",
+               (unsigned long long)sh->sector, i, atomic_read(&sh->count),
+               uptodate);
+       if (i == disks) {
+               BUG();
+               return 0;
+       }
+
+       if (!uptodate)
+               md_error(conf->mddev, conf->disks[i].rdev);
+
+       rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
+       
+       clear_bit(R5_LOCKED, &sh->dev[i].flags);
+       set_bit(STRIPE_HANDLE, &sh->state);
+       release_stripe(sh);
+       return 0;
+}
+
+
+static sector_t compute_blocknr(struct stripe_head *sh, int i);
+       
+static void raid5_build_block (struct stripe_head *sh, int i)
+{
+       struct r5dev *dev = &sh->dev[i];
+
+       bio_init(&dev->req);
+       dev->req.bi_io_vec = &dev->vec;
+       dev->req.bi_vcnt++;
+       dev->req.bi_max_vecs++;
+       dev->vec.bv_page = dev->page;
+       dev->vec.bv_len = STRIPE_SIZE;
+       dev->vec.bv_offset = 0;
+
+       dev->req.bi_sector = sh->sector;
+       dev->req.bi_private = sh;
+
+       dev->flags = 0;
+       dev->sector = compute_blocknr(sh, i);
+}
+
+static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+       char b[BDEVNAME_SIZE];
+       raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
+       pr_debug("raid5: error called\n");
+
+       if (!test_bit(Faulty, &rdev->flags)) {
+               set_bit(MD_CHANGE_DEVS, &mddev->flags);
+               if (test_and_clear_bit(In_sync, &rdev->flags)) {
+                       unsigned long flags;
+                       spin_lock_irqsave(&conf->device_lock, flags);
+                       mddev->degraded++;
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
+                       /*
+                        * if recovery was running, make sure it aborts.
+                        */
+                       set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+               }
+               set_bit(Faulty, &rdev->flags);
+               printk (KERN_ALERT
+                       "raid5: Disk failure on %s, disabling device."
+                       " Operation continuing on %d devices\n",
+                       bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded);
+       }
+}
+
+/*
+ * Input: a 'big' sector number,
+ * Output: index of the data and parity disk, and the sector # in them.
+ */
+static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
+                       unsigned int data_disks, unsigned int * dd_idx,
+                       unsigned int * pd_idx, raid5_conf_t *conf)
+{
+       long stripe;
+       unsigned long chunk_number;
+       unsigned int chunk_offset;
+       sector_t new_sector;
+       int sectors_per_chunk = conf->chunk_size >> 9;
+
+       /* First compute the information on this sector */
+
+       /*
+        * Compute the chunk number and the sector offset inside the chunk
+        */
+       chunk_offset = sector_div(r_sector, sectors_per_chunk);
+       chunk_number = r_sector;
+       BUG_ON(r_sector != chunk_number);
+
+       /*
+        * Compute the stripe number
+        */
+       stripe = chunk_number / data_disks;
+
+       /*
+        * Compute the data disk and parity disk indexes inside the stripe
+        */
+       *dd_idx = chunk_number % data_disks;
+
+       /*
+        * Select the parity disk based on the user selected algorithm.
+        */
+       switch(conf->level) {
+       case 4:
+               *pd_idx = data_disks;
+               break;
+       case 5:
+               switch (conf->algorithm) {
+               case ALGORITHM_LEFT_ASYMMETRIC:
+                       *pd_idx = data_disks - stripe % raid_disks;
+                       if (*dd_idx >= *pd_idx)
                                (*dd_idx)++;
                        break;
                case ALGORITHM_RIGHT_ASYMMETRIC:
@@ -775,557 +1368,1228 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
                        printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
                                conf->algorithm);
                }
-               break;
+               break;
+       }
+
+       /*
+        * Finally, compute the new sector number
+        */
+       new_sector = (sector_t)stripe * sectors_per_chunk + chunk_offset;
+       return new_sector;
+}
+
+
+static sector_t compute_blocknr(struct stripe_head *sh, int i)
+{
+       raid5_conf_t *conf = sh->raid_conf;
+       int raid_disks = sh->disks;
+       int data_disks = raid_disks - conf->max_degraded;
+       sector_t new_sector = sh->sector, check;
+       int sectors_per_chunk = conf->chunk_size >> 9;
+       sector_t stripe;
+       int chunk_offset;
+       int chunk_number, dummy1, dummy2, dd_idx = i;
+       sector_t r_sector;
+
+
+       chunk_offset = sector_div(new_sector, sectors_per_chunk);
+       stripe = new_sector;
+       BUG_ON(new_sector != stripe);
+
+       if (i == sh->pd_idx)
+               return 0;
+       switch(conf->level) {
+       case 4: break;
+       case 5:
+               switch (conf->algorithm) {
+               case ALGORITHM_LEFT_ASYMMETRIC:
+               case ALGORITHM_RIGHT_ASYMMETRIC:
+                       if (i > sh->pd_idx)
+                               i--;
+                       break;
+               case ALGORITHM_LEFT_SYMMETRIC:
+               case ALGORITHM_RIGHT_SYMMETRIC:
+                       if (i < sh->pd_idx)
+                               i += raid_disks;
+                       i -= (sh->pd_idx + 1);
+                       break;
+               default:
+                       printk(KERN_ERR "raid5: unsupported algorithm %d\n",
+                              conf->algorithm);
+               }
+               break;
+       case 6:
+               if (i == raid6_next_disk(sh->pd_idx, raid_disks))
+                       return 0; /* It is the Q disk */
+               switch (conf->algorithm) {
+               case ALGORITHM_LEFT_ASYMMETRIC:
+               case ALGORITHM_RIGHT_ASYMMETRIC:
+                       if (sh->pd_idx == raid_disks-1)
+                               i--;    /* Q D D D P */
+                       else if (i > sh->pd_idx)
+                               i -= 2; /* D D P Q D */
+                       break;
+               case ALGORITHM_LEFT_SYMMETRIC:
+               case ALGORITHM_RIGHT_SYMMETRIC:
+                       if (sh->pd_idx == raid_disks-1)
+                               i--; /* Q D D D P */
+                       else {
+                               /* D D P Q D */
+                               if (i < sh->pd_idx)
+                                       i += raid_disks;
+                               i -= (sh->pd_idx + 2);
+                       }
+                       break;
+               default:
+                       printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
+                               conf->algorithm);
+               }
+               break;
+       }
+
+       chunk_number = stripe * data_disks + i;
+       r_sector = (sector_t)chunk_number * sectors_per_chunk + chunk_offset;
+
+       check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf);
+       if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) {
+               printk(KERN_ERR "compute_blocknr: map not correct\n");
+               return 0;
+       }
+       return r_sector;
+}
+
+
+
+/*
+ * Copy data between a page in the stripe cache, and one or more bion
+ * The page could align with the middle of the bio, or there could be
+ * several bion, each with several bio_vecs, which cover part of the page
+ * Multiple bion are linked together on bi_next.  There may be extras
+ * at the end of this list.  We ignore them.
+ */
+static void copy_data(int frombio, struct bio *bio,
+                    struct page *page,
+                    sector_t sector)
+{
+       char *pa = page_address(page);
+       struct bio_vec *bvl;
+       int i;
+       int page_offset;
+
+       if (bio->bi_sector >= sector)
+               page_offset = (signed)(bio->bi_sector - sector) * 512;
+       else
+               page_offset = (signed)(sector - bio->bi_sector) * -512;
+       bio_for_each_segment(bvl, bio, i) {
+               int len = bio_iovec_idx(bio,i)->bv_len;
+               int clen;
+               int b_offset = 0;
+
+               if (page_offset < 0) {
+                       b_offset = -page_offset;
+                       page_offset += b_offset;
+                       len -= b_offset;
+               }
+
+               if (len > 0 && page_offset + len > STRIPE_SIZE)
+                       clen = STRIPE_SIZE - page_offset;
+               else clen = len;
+
+               if (clen > 0) {
+                       char *ba = __bio_kmap_atomic(bio, i, KM_USER0);
+                       if (frombio)
+                               memcpy(pa+page_offset, ba+b_offset, clen);
+                       else
+                               memcpy(ba+b_offset, pa+page_offset, clen);
+                       __bio_kunmap_atomic(ba, KM_USER0);
+               }
+               if (clen < len) /* hit end of page */
+                       break;
+               page_offset +=  len;
+       }
+}
+
+#define check_xor()    do {                                              \
+                               if (count == MAX_XOR_BLOCKS) {            \
+                               xor_blocks(count, STRIPE_SIZE, dest, ptr);\
+                               count = 0;                                \
+                          }                                              \
+                       } while(0)
+
+static void compute_parity6(struct stripe_head *sh, int method)
+{
+       raid6_conf_t *conf = sh->raid_conf;
+       int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = sh->disks, count;
+       struct bio *chosen;
+       /**** FIX THIS: This could be very bad if disks is close to 256 ****/
+       void *ptrs[disks];
+
+       qd_idx = raid6_next_disk(pd_idx, disks);
+       d0_idx = raid6_next_disk(qd_idx, disks);
+
+       pr_debug("compute_parity, stripe %llu, method %d\n",
+               (unsigned long long)sh->sector, method);
+
+       switch(method) {
+       case READ_MODIFY_WRITE:
+               BUG();          /* READ_MODIFY_WRITE N/A for RAID-6 */
+       case RECONSTRUCT_WRITE:
+               for (i= disks; i-- ;)
+                       if ( i != pd_idx && i != qd_idx && sh->dev[i].towrite ) {
+                               chosen = sh->dev[i].towrite;
+                               sh->dev[i].towrite = NULL;
+
+                               if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+                                       wake_up(&conf->wait_for_overlap);
+
+                               BUG_ON(sh->dev[i].written);
+                               sh->dev[i].written = chosen;
+                       }
+               break;
+       case CHECK_PARITY:
+               BUG();          /* Not implemented yet */
+       }
+
+       for (i = disks; i--;)
+               if (sh->dev[i].written) {
+                       sector_t sector = sh->dev[i].sector;
+                       struct bio *wbi = sh->dev[i].written;
+                       while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {
+                               copy_data(1, wbi, sh->dev[i].page, sector);
+                               wbi = r5_next_bio(wbi, sector);
+                       }
+
+                       set_bit(R5_LOCKED, &sh->dev[i].flags);
+                       set_bit(R5_UPTODATE, &sh->dev[i].flags);
+               }
+
+//     switch(method) {
+//     case RECONSTRUCT_WRITE:
+//     case CHECK_PARITY:
+//     case UPDATE_PARITY:
+               /* Note that unlike RAID-5, the ordering of the disks matters greatly. */
+               /* FIX: Is this ordering of drives even remotely optimal? */
+               count = 0;
+               i = d0_idx;
+               do {
+                       ptrs[count++] = page_address(sh->dev[i].page);
+                       if (count <= disks-2 && !test_bit(R5_UPTODATE, &sh->dev[i].flags))
+                               printk("block %d/%d not uptodate on parity calc\n", i,count);
+                       i = raid6_next_disk(i, disks);
+               } while ( i != d0_idx );
+//             break;
+//     }
+
+       raid6_call.gen_syndrome(disks, STRIPE_SIZE, ptrs);
+
+       switch(method) {
+       case RECONSTRUCT_WRITE:
+               set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+               set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags);
+               set_bit(R5_LOCKED,   &sh->dev[pd_idx].flags);
+               set_bit(R5_LOCKED,   &sh->dev[qd_idx].flags);
+               break;
+       case UPDATE_PARITY:
+               set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+               set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags);
+               break;
+       }
+}
+
+
+/* Compute one missing block */
+static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
+{
+       int i, count, disks = sh->disks;
+       void *ptr[MAX_XOR_BLOCKS], *dest, *p;
+       int pd_idx = sh->pd_idx;
+       int qd_idx = raid6_next_disk(pd_idx, disks);
+
+       pr_debug("compute_block_1, stripe %llu, idx %d\n",
+               (unsigned long long)sh->sector, dd_idx);
+
+       if ( dd_idx == qd_idx ) {
+               /* We're actually computing the Q drive */
+               compute_parity6(sh, UPDATE_PARITY);
+       } else {
+               dest = page_address(sh->dev[dd_idx].page);
+               if (!nozero) memset(dest, 0, STRIPE_SIZE);
+               count = 0;
+               for (i = disks ; i--; ) {
+                       if (i == dd_idx || i == qd_idx)
+                               continue;
+                       p = page_address(sh->dev[i].page);
+                       if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
+                               ptr[count++] = p;
+                       else
+                               printk("compute_block() %d, stripe %llu, %d"
+                                      " not present\n", dd_idx,
+                                      (unsigned long long)sh->sector, i);
+
+                       check_xor();
+               }
+               if (count)
+                       xor_blocks(count, STRIPE_SIZE, dest, ptr);
+               if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
+               else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
        }
-
-       /*
-        * Finally, compute the new sector number
-        */
-       new_sector = (sector_t)stripe * sectors_per_chunk + chunk_offset;
-       return new_sector;
 }
 
-
-static sector_t compute_blocknr(struct stripe_head *sh, int i)
+/* Compute two missing blocks */
+static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
 {
-       raid5_conf_t *conf = sh->raid_conf;
-       int raid_disks = sh->disks;
-       int data_disks = raid_disks - conf->max_degraded;
-       sector_t new_sector = sh->sector, check;
-       int sectors_per_chunk = conf->chunk_size >> 9;
-       sector_t stripe;
-       int chunk_offset;
-       int chunk_number, dummy1, dummy2, dd_idx = i;
-       sector_t r_sector;
+       int i, count, disks = sh->disks;
+       int pd_idx = sh->pd_idx;
+       int qd_idx = raid6_next_disk(pd_idx, disks);
+       int d0_idx = raid6_next_disk(qd_idx, disks);
+       int faila, failb;
 
+       /* faila and failb are disk numbers relative to d0_idx */
+       /* pd_idx become disks-2 and qd_idx become disks-1 */
+       faila = (dd_idx1 < d0_idx) ? dd_idx1+(disks-d0_idx) : dd_idx1-d0_idx;
+       failb = (dd_idx2 < d0_idx) ? dd_idx2+(disks-d0_idx) : dd_idx2-d0_idx;
 
-       chunk_offset = sector_div(new_sector, sectors_per_chunk);
-       stripe = new_sector;
-       BUG_ON(new_sector != stripe);
+       BUG_ON(faila == failb);
+       if ( failb < faila ) { int tmp = faila; faila = failb; failb = tmp; }
 
-       if (i == sh->pd_idx)
-               return 0;
-       switch(conf->level) {
-       case 4: break;
-       case 5:
-               switch (conf->algorithm) {
-               case ALGORITHM_LEFT_ASYMMETRIC:
-               case ALGORITHM_RIGHT_ASYMMETRIC:
-                       if (i > sh->pd_idx)
-                               i--;
-                       break;
-               case ALGORITHM_LEFT_SYMMETRIC:
-               case ALGORITHM_RIGHT_SYMMETRIC:
-                       if (i < sh->pd_idx)
-                               i += raid_disks;
-                       i -= (sh->pd_idx + 1);
-                       break;
-               default:
-                       printk(KERN_ERR "raid5: unsupported algorithm %d\n",
-                              conf->algorithm);
-               }
-               break;
-       case 6:
-               if (i == raid6_next_disk(sh->pd_idx, raid_disks))
-                       return 0; /* It is the Q disk */
-               switch (conf->algorithm) {
-               case ALGORITHM_LEFT_ASYMMETRIC:
-               case ALGORITHM_RIGHT_ASYMMETRIC:
-                       if (sh->pd_idx == raid_disks-1)
-                               i--;    /* Q D D D P */
-                       else if (i > sh->pd_idx)
-                               i -= 2; /* D D P Q D */
-                       break;
-               case ALGORITHM_LEFT_SYMMETRIC:
-               case ALGORITHM_RIGHT_SYMMETRIC:
-                       if (sh->pd_idx == raid_disks-1)
-                               i--; /* Q D D D P */
-                       else {
-                               /* D D P Q D */
-                               if (i < sh->pd_idx)
-                                       i += raid_disks;
-                               i -= (sh->pd_idx + 2);
-                       }
-                       break;
-               default:
-                       printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
-                               conf->algorithm);
+       pr_debug("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
+              (unsigned long long)sh->sector, dd_idx1, dd_idx2, faila, failb);
+
+       if ( failb == disks-1 ) {
+               /* Q disk is one of the missing disks */
+               if ( faila == disks-2 ) {
+                       /* Missing P+Q, just recompute */
+                       compute_parity6(sh, UPDATE_PARITY);
+                       return;
+               } else {
+                       /* We're missing D+Q; recompute D from P */
+                       compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1, 0);
+                       compute_parity6(sh, UPDATE_PARITY); /* Is this necessary? */
+                       return;
                }
-               break;
        }
 
-       chunk_number = stripe * data_disks + i;
-       r_sector = (sector_t)chunk_number * sectors_per_chunk + chunk_offset;
+       /* We're missing D+P or D+D; build pointer table */
+       {
+               /**** FIX THIS: This could be very bad if disks is close to 256 ****/
+               void *ptrs[disks];
 
-       check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf);
-       if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) {
-               printk(KERN_ERR "compute_blocknr: map not correct\n");
-               return 0;
+               count = 0;
+               i = d0_idx;
+               do {
+                       ptrs[count++] = page_address(sh->dev[i].page);
+                       i = raid6_next_disk(i, disks);
+                       if (i != dd_idx1 && i != dd_idx2 &&
+                           !test_bit(R5_UPTODATE, &sh->dev[i].flags))
+                               printk("compute_2 with missing block %d/%d\n", count, i);
+               } while ( i != d0_idx );
+
+               if ( failb == disks-2 ) {
+                       /* We're missing D+P. */
+                       raid6_datap_recov(disks, STRIPE_SIZE, faila, ptrs);
+               } else {
+                       /* We're missing D+D. */
+                       raid6_2data_recov(disks, STRIPE_SIZE, faila, failb, ptrs);
+               }
+
+               /* Both the above update both missing blocks */
+               set_bit(R5_UPTODATE, &sh->dev[dd_idx1].flags);
+               set_bit(R5_UPTODATE, &sh->dev[dd_idx2].flags);
        }
-       return r_sector;
 }
 
+static int
+handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
+{
+       int i, pd_idx = sh->pd_idx, disks = sh->disks;
+       int locked = 0;
 
+       if (rcw) {
+               /* if we are not expanding this is a proper write request, and
+                * there will be bios with new data to be drained into the
+                * stripe cache
+                */
+               if (!expand) {
+                       set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+                       sh->ops.count++;
+               }
 
-/*
- * Copy data between a page in the stripe cache, and one or more bion
- * The page could align with the middle of the bio, or there could be
- * several bion, each with several bio_vecs, which cover part of the page
- * Multiple bion are linked together on bi_next.  There may be extras
- * at the end of this list.  We ignore them.
- */
-static void copy_data(int frombio, struct bio *bio,
-                    struct page *page,
-                    sector_t sector)
-{
-       char *pa = page_address(page);
-       struct bio_vec *bvl;
-       int i;
-       int page_offset;
+               set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+               sh->ops.count++;
 
-       if (bio->bi_sector >= sector)
-               page_offset = (signed)(bio->bi_sector - sector) * 512;
-       else
-               page_offset = (signed)(sector - bio->bi_sector) * -512;
-       bio_for_each_segment(bvl, bio, i) {
-               int len = bio_iovec_idx(bio,i)->bv_len;
-               int clen;
-               int b_offset = 0;
+               for (i = disks; i--; ) {
+                       struct r5dev *dev = &sh->dev[i];
 
-               if (page_offset < 0) {
-                       b_offset = -page_offset;
-                       page_offset += b_offset;
-                       len -= b_offset;
+                       if (dev->towrite) {
+                               set_bit(R5_LOCKED, &dev->flags);
+                               if (!expand)
+                                       clear_bit(R5_UPTODATE, &dev->flags);
+                               locked++;
+                       }
                }
+       } else {
+               BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
+                       test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
 
-               if (len > 0 && page_offset + len > STRIPE_SIZE)
-                       clen = STRIPE_SIZE - page_offset;
-               else clen = len;
+               set_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+               set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+               set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
 
-               if (clen > 0) {
-                       char *ba = __bio_kmap_atomic(bio, i, KM_USER0);
-                       if (frombio)
-                               memcpy(pa+page_offset, ba+b_offset, clen);
-                       else
-                               memcpy(ba+b_offset, pa+page_offset, clen);
-                       __bio_kunmap_atomic(ba, KM_USER0);
+               sh->ops.count += 3;
+
+               for (i = disks; i--; ) {
+                       struct r5dev *dev = &sh->dev[i];
+                       if (i == pd_idx)
+                               continue;
+
+                       /* For a read-modify write there may be blocks that are
+                        * locked for reading while others are ready to be
+                        * written so we distinguish these blocks by the
+                        * R5_Wantprexor bit
+                        */
+                       if (dev->towrite &&
+                           (test_bit(R5_UPTODATE, &dev->flags) ||
+                           test_bit(R5_Wantcompute, &dev->flags))) {
+                               set_bit(R5_Wantprexor, &dev->flags);
+                               set_bit(R5_LOCKED, &dev->flags);
+                               clear_bit(R5_UPTODATE, &dev->flags);
+                               locked++;
+                       }
                }
-               if (clen < len) /* hit end of page */
-                       break;
-               page_offset +=  len;
        }
-}
 
-#define check_xor()    do {                                            \
-                          if (count == MAX_XOR_BLOCKS) {               \
-                               xor_block(count, STRIPE_SIZE, ptr);     \
-                               count = 1;                              \
-                          }                                            \
-                       } while(0)
+       /* keep the parity disk locked while asynchronous operations
+        * are in flight
+        */
+       set_bit(R5_LOCKED, &sh->dev[pd_idx].flags);
+       clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+       locked++;
+
+       pr_debug("%s: stripe %llu locked: %d pending: %lx\n",
+               __FUNCTION__, (unsigned long long)sh->sector,
+               locked, sh->ops.pending);
 
+       return locked;
+}
 
-static void compute_block(struct stripe_head *sh, int dd_idx)
+/*
+ * Each stripe/dev can have one or more bion attached.
+ * toread/towrite point to the first in a chain.
+ * The bi_next chain must be in order.
+ */
+static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
 {
-       int i, count, disks = sh->disks;
-       void *ptr[MAX_XOR_BLOCKS], *p;
+       struct bio **bip;
+       raid5_conf_t *conf = sh->raid_conf;
+       int firstwrite=0;
+
+       pr_debug("adding bh b#%llu to stripe s#%llu\n",
+               (unsigned long long)bi->bi_sector,
+               (unsigned long long)sh->sector);
+
+
+       spin_lock(&sh->lock);
+       spin_lock_irq(&conf->device_lock);
+       if (forwrite) {
+               bip = &sh->dev[dd_idx].towrite;
+               if (*bip == NULL && sh->dev[dd_idx].written == NULL)
+                       firstwrite = 1;
+       } else
+               bip = &sh->dev[dd_idx].toread;
+       while (*bip && (*bip)->bi_sector < bi->bi_sector) {
+               if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
+                       goto overlap;
+               bip = & (*bip)->bi_next;
+       }
+       if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
+               goto overlap;
+
+       BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
+       if (*bip)
+               bi->bi_next = *bip;
+       *bip = bi;
+       bi->bi_phys_segments ++;
+       spin_unlock_irq(&conf->device_lock);
+       spin_unlock(&sh->lock);
 
-       PRINTK("compute_block, stripe %llu, idx %d\n", 
+       pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n",
+               (unsigned long long)bi->bi_sector,
                (unsigned long long)sh->sector, dd_idx);
 
-       ptr[0] = page_address(sh->dev[dd_idx].page);
-       memset(ptr[0], 0, STRIPE_SIZE);
-       count = 1;
-       for (i = disks ; i--; ) {
-               if (i == dd_idx)
-                       continue;
-               p = page_address(sh->dev[i].page);
-               if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
-                       ptr[count++] = p;
-               else
-                       printk(KERN_ERR "compute_block() %d, stripe %llu, %d"
-                               " not present\n", dd_idx,
-                               (unsigned long long)sh->sector, i);
+       if (conf->mddev->bitmap && firstwrite) {
+               bitmap_startwrite(conf->mddev->bitmap, sh->sector,
+                                 STRIPE_SECTORS, 0);
+               sh->bm_seq = conf->seq_flush+1;
+               set_bit(STRIPE_BIT_DELAY, &sh->state);
+       }
 
-               check_xor();
+       if (forwrite) {
+               /* check if page is covered */
+               sector_t sector = sh->dev[dd_idx].sector;
+               for (bi=sh->dev[dd_idx].towrite;
+                    sector < sh->dev[dd_idx].sector + STRIPE_SECTORS &&
+                            bi && bi->bi_sector <= sector;
+                    bi = r5_next_bio(bi, sh->dev[dd_idx].sector)) {
+                       if (bi->bi_sector + (bi->bi_size>>9) >= sector)
+                               sector = bi->bi_sector + (bi->bi_size>>9);
+               }
+               if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS)
+                       set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags);
        }
-       if (count != 1)
-               xor_block(count, STRIPE_SIZE, ptr);
-       set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
+       return 1;
+
+ overlap:
+       set_bit(R5_Overlap, &sh->dev[dd_idx].flags);
+       spin_unlock_irq(&conf->device_lock);
+       spin_unlock(&sh->lock);
+       return 0;
 }
 
-static void compute_parity5(struct stripe_head *sh, int method)
+static void end_reshape(raid5_conf_t *conf);
+
+static int page_is_zero(struct page *p)
 {
-       raid5_conf_t *conf = sh->raid_conf;
-       int i, pd_idx = sh->pd_idx, disks = sh->disks, count;
-       void *ptr[MAX_XOR_BLOCKS];
-       struct bio *chosen;
+       char *a = page_address(p);
+       return ((*(u32*)a) == 0 &&
+               memcmp(a, a+4, STRIPE_SIZE-4)==0);
+}
 
-       PRINTK("compute_parity5, stripe %llu, method %d\n",
-               (unsigned long long)sh->sector, method);
+static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
+{
+       int sectors_per_chunk = conf->chunk_size >> 9;
+       int pd_idx, dd_idx;
+       int chunk_offset = sector_div(stripe, sectors_per_chunk);
 
-       count = 1;
-       ptr[0] = page_address(sh->dev[pd_idx].page);
-       switch(method) {
-       case READ_MODIFY_WRITE:
-               BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags));
-               for (i=disks ; i-- ;) {
-                       if (i==pd_idx)
-                               continue;
-                       if (sh->dev[i].towrite &&
-                           test_bit(R5_UPTODATE, &sh->dev[i].flags)) {
-                               ptr[count++] = page_address(sh->dev[i].page);
-                               chosen = sh->dev[i].towrite;
-                               sh->dev[i].towrite = NULL;
+       raid5_compute_sector(stripe * (disks - conf->max_degraded)
+                            *sectors_per_chunk + chunk_offset,
+                            disks, disks - conf->max_degraded,
+                            &dd_idx, &pd_idx, conf);
+       return pd_idx;
+}
 
-                               if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-                                       wake_up(&conf->wait_for_overlap);
+static void
+handle_requests_to_failed_array(raid5_conf_t *conf, struct stripe_head *sh,
+                               struct stripe_head_state *s, int disks,
+                               struct bio **return_bi)
+{
+       int i;
+       for (i = disks; i--; ) {
+               struct bio *bi;
+               int bitmap_end = 0;
 
-                               BUG_ON(sh->dev[i].written);
-                               sh->dev[i].written = chosen;
-                               check_xor();
-                       }
+               if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+                       mdk_rdev_t *rdev;
+                       rcu_read_lock();
+                       rdev = rcu_dereference(conf->disks[i].rdev);
+                       if (rdev && test_bit(In_sync, &rdev->flags))
+                               /* multiple read failures in one stripe */
+                               md_error(conf->mddev, rdev);
+                       rcu_read_unlock();
+               }
+               spin_lock_irq(&conf->device_lock);
+               /* fail all writes first */
+               bi = sh->dev[i].towrite;
+               sh->dev[i].towrite = NULL;
+               if (bi) {
+                       s->to_write--;
+                       bitmap_end = 1;
                }
-               break;
-       case RECONSTRUCT_WRITE:
-               memset(ptr[0], 0, STRIPE_SIZE);
-               for (i= disks; i-- ;)
-                       if (i!=pd_idx && sh->dev[i].towrite) {
-                               chosen = sh->dev[i].towrite;
-                               sh->dev[i].towrite = NULL;
 
-                               if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-                                       wake_up(&conf->wait_for_overlap);
+               if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+                       wake_up(&conf->wait_for_overlap);
 
-                               BUG_ON(sh->dev[i].written);
-                               sh->dev[i].written = chosen;
+               while (bi && bi->bi_sector <
+                       sh->dev[i].sector + STRIPE_SECTORS) {
+                       struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
+                       clear_bit(BIO_UPTODATE, &bi->bi_flags);
+                       if (--bi->bi_phys_segments == 0) {
+                               md_write_end(conf->mddev);
+                               bi->bi_next = *return_bi;
+                               *return_bi = bi;
                        }
-               break;
-       case CHECK_PARITY:
-               break;
-       }
-       if (count>1) {
-               xor_block(count, STRIPE_SIZE, ptr);
-               count = 1;
-       }
-       
-       for (i = disks; i--;)
-               if (sh->dev[i].written) {
-                       sector_t sector = sh->dev[i].sector;
-                       struct bio *wbi = sh->dev[i].written;
-                       while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {
-                               copy_data(1, wbi, sh->dev[i].page, sector);
-                               wbi = r5_next_bio(wbi, sector);
+                       bi = nextbi;
+               }
+               /* and fail all 'written' */
+               bi = sh->dev[i].written;
+               sh->dev[i].written = NULL;
+               if (bi) bitmap_end = 1;
+               while (bi && bi->bi_sector <
+                      sh->dev[i].sector + STRIPE_SECTORS) {
+                       struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
+                       clear_bit(BIO_UPTODATE, &bi->bi_flags);
+                       if (--bi->bi_phys_segments == 0) {
+                               md_write_end(conf->mddev);
+                               bi->bi_next = *return_bi;
+                               *return_bi = bi;
                        }
-
-                       set_bit(R5_LOCKED, &sh->dev[i].flags);
-                       set_bit(R5_UPTODATE, &sh->dev[i].flags);
+                       bi = bi2;
                }
 
-       switch(method) {
-       case RECONSTRUCT_WRITE:
-       case CHECK_PARITY:
-               for (i=disks; i--;)
-                       if (i != pd_idx) {
-                               ptr[count++] = page_address(sh->dev[i].page);
-                               check_xor();
-                       }
-               break;
-       case READ_MODIFY_WRITE:
-               for (i = disks; i--;)
-                       if (sh->dev[i].written) {
-                               ptr[count++] = page_address(sh->dev[i].page);
-                               check_xor();
+               /* fail any reads if this device is non-operational and
+                * the data has not reached the cache yet.
+                */
+               if (!test_bit(R5_Wantfill, &sh->dev[i].flags) &&
+                   (!test_bit(R5_Insync, &sh->dev[i].flags) ||
+                     test_bit(R5_ReadError, &sh->dev[i].flags))) {
+                       bi = sh->dev[i].toread;
+                       sh->dev[i].toread = NULL;
+                       if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+                               wake_up(&conf->wait_for_overlap);
+                       if (bi) s->to_read--;
+                       while (bi && bi->bi_sector <
+                              sh->dev[i].sector + STRIPE_SECTORS) {
+                               struct bio *nextbi =
+                                       r5_next_bio(bi, sh->dev[i].sector);
+                               clear_bit(BIO_UPTODATE, &bi->bi_flags);
+                               if (--bi->bi_phys_segments == 0) {
+                                       bi->bi_next = *return_bi;
+                                       *return_bi = bi;
+                               }
+                               bi = nextbi;
                        }
+               }
+               spin_unlock_irq(&conf->device_lock);
+               if (bitmap_end)
+                       bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+                                       STRIPE_SECTORS, 0, 0);
        }
-       if (count != 1)
-               xor_block(count, STRIPE_SIZE, ptr);
-       
-       if (method != CHECK_PARITY) {
-               set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-               set_bit(R5_LOCKED,   &sh->dev[pd_idx].flags);
-       } else
-               clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+
 }
 
-static void compute_parity6(struct stripe_head *sh, int method)
+/* __handle_issuing_new_read_requests5 - returns 0 if there are no more disks
+ * to process
+ */
+static int __handle_issuing_new_read_requests5(struct stripe_head *sh,
+                       struct stripe_head_state *s, int disk_idx, int disks)
 {
-       raid6_conf_t *conf = sh->raid_conf;
-       int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = sh->disks, count;
-       struct bio *chosen;
-       /**** FIX THIS: This could be very bad if disks is close to 256 ****/
-       void *ptrs[disks];
+       struct r5dev *dev = &sh->dev[disk_idx];
+       struct r5dev *failed_dev = &sh->dev[s->failed_num];
 
-       qd_idx = raid6_next_disk(pd_idx, disks);
-       d0_idx = raid6_next_disk(qd_idx, disks);
+       /* don't schedule compute operations or reads on the parity block while
+        * a check is in flight
+        */
+       if ((disk_idx == sh->pd_idx) &&
+            test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
+               return ~0;
+
+       /* is the data in this block needed, and can we get it? */
+       if (!test_bit(R5_LOCKED, &dev->flags) &&
+           !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread ||
+           (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
+            s->syncing || s->expanding || (s->failed &&
+            (failed_dev->toread || (failed_dev->towrite &&
+            !test_bit(R5_OVERWRITE, &failed_dev->flags)
+            ))))) {
+               /* 1/ We would like to get this block, possibly by computing it,
+                * but we might not be able to.
+                *
+                * 2/ Since parity check operations potentially make the parity
+                * block !uptodate it will need to be refreshed before any
+                * compute operations on data disks are scheduled.
+                *
+                * 3/ We hold off parity block re-reads until check operations
+                * have quiesced.
+                */
+               if ((s->uptodate == disks - 1) &&
+                   !test_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
+                       set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+                       set_bit(R5_Wantcompute, &dev->flags);
+                       sh->ops.target = disk_idx;
+                       s->req_compute = 1;
+                       sh->ops.count++;
+                       /* Careful: from this point on 'uptodate' is in the eye
+                        * of raid5_run_ops which services 'compute' operations
+                        * before writes. R5_Wantcompute flags a block that will
+                        * be R5_UPTODATE by the time it is needed for a
+                        * subsequent operation.
+                        */
+                       s->uptodate++;
+                       return 0; /* uptodate + compute == disks */
+               } else if ((s->uptodate < disks - 1) &&
+                       test_bit(R5_Insync, &dev->flags)) {
+                       /* Note: we hold off compute operations while checks are
+                        * in flight, but we still prefer 'compute' over 'read'
+                        * hence we only read if (uptodate < * disks-1)
+                        */
+                       set_bit(R5_LOCKED, &dev->flags);
+                       set_bit(R5_Wantread, &dev->flags);
+                       if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+                               sh->ops.count++;
+                       s->locked++;
+                       pr_debug("Reading block %d (sync=%d)\n", disk_idx,
+                               s->syncing);
+               }
+       }
 
-       PRINTK("compute_parity, stripe %llu, method %d\n",
-               (unsigned long long)sh->sector, method);
+       return ~0;
+}
 
-       switch(method) {
-       case READ_MODIFY_WRITE:
-               BUG();          /* READ_MODIFY_WRITE N/A for RAID-6 */
-       case RECONSTRUCT_WRITE:
-               for (i= disks; i-- ;)
-                       if ( i != pd_idx && i != qd_idx && sh->dev[i].towrite ) {
-                               chosen = sh->dev[i].towrite;
-                               sh->dev[i].towrite = NULL;
+static void handle_issuing_new_read_requests5(struct stripe_head *sh,
+                       struct stripe_head_state *s, int disks)
+{
+       int i;
 
-                               if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-                                       wake_up(&conf->wait_for_overlap);
+       /* Clear completed compute operations.  Parity recovery
+        * (STRIPE_OP_MOD_REPAIR_PD) implies a write-back which is handled
+        * later on in this routine
+        */
+       if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
+               !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
+               clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+               clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
+               clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+       }
 
-                               BUG_ON(sh->dev[i].written);
-                               sh->dev[i].written = chosen;
-                       }
-               break;
-       case CHECK_PARITY:
-               BUG();          /* Not implemented yet */
+       /* look for blocks to read/compute, skip this if a compute
+        * is already in flight, or if the stripe contents are in the
+        * midst of changing due to a write
+        */
+       if (!test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
+               !test_bit(STRIPE_OP_PREXOR, &sh->ops.pending) &&
+               !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+               for (i = disks; i--; )
+                       if (__handle_issuing_new_read_requests5(
+                               sh, s, i, disks) == 0)
+                               break;
        }
+       set_bit(STRIPE_HANDLE, &sh->state);
+}
 
-       for (i = disks; i--;)
-               if (sh->dev[i].written) {
-                       sector_t sector = sh->dev[i].sector;
-                       struct bio *wbi = sh->dev[i].written;
-                       while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {
-                               copy_data(1, wbi, sh->dev[i].page, sector);
-                               wbi = r5_next_bio(wbi, sector);
+static void handle_issuing_new_read_requests6(struct stripe_head *sh,
+                       struct stripe_head_state *s, struct r6_state *r6s,
+                       int disks)
+{
+       int i;
+       for (i = disks; i--; ) {
+               struct r5dev *dev = &sh->dev[i];
+               if (!test_bit(R5_LOCKED, &dev->flags) &&
+                   !test_bit(R5_UPTODATE, &dev->flags) &&
+                   (dev->toread || (dev->towrite &&
+                    !test_bit(R5_OVERWRITE, &dev->flags)) ||
+                    s->syncing || s->expanding ||
+                    (s->failed >= 1 &&
+                     (sh->dev[r6s->failed_num[0]].toread ||
+                      s->to_write)) ||
+                    (s->failed >= 2 &&
+                     (sh->dev[r6s->failed_num[1]].toread ||
+                      s->to_write)))) {
+                       /* we would like to get this block, possibly
+                        * by computing it, but we might not be able to
+                        */
+                       if (s->uptodate == disks-1) {
+                               pr_debug("Computing stripe %llu block %d\n",
+                                      (unsigned long long)sh->sector, i);
+                               compute_block_1(sh, i, 0);
+                               s->uptodate++;
+                       } else if ( s->uptodate == disks-2 && s->failed >= 2 ) {
+                               /* Computing 2-failure is *very* expensive; only
+                                * do it if failed >= 2
+                                */
+                               int other;
+                               for (other = disks; other--; ) {
+                                       if (other == i)
+                                               continue;
+                                       if (!test_bit(R5_UPTODATE,
+                                             &sh->dev[other].flags))
+                                               break;
+                               }
+                               BUG_ON(other < 0);
+                               pr_debug("Computing stripe %llu blocks %d,%d\n",
+                                      (unsigned long long)sh->sector,
+                                      i, other);
+                               compute_block_2(sh, i, other);
+                               s->uptodate += 2;
+                       } else if (test_bit(R5_Insync, &dev->flags)) {
+                               set_bit(R5_LOCKED, &dev->flags);
+                               set_bit(R5_Wantread, &dev->flags);
+                               s->locked++;
+                               pr_debug("Reading block %d (sync=%d)\n",
+                                       i, s->syncing);
                        }
-
-                       set_bit(R5_LOCKED, &sh->dev[i].flags);
-                       set_bit(R5_UPTODATE, &sh->dev[i].flags);
                }
+       }
+       set_bit(STRIPE_HANDLE, &sh->state);
+}
 
-//     switch(method) {
-//     case RECONSTRUCT_WRITE:
-//     case CHECK_PARITY:
-//     case UPDATE_PARITY:
-               /* Note that unlike RAID-5, the ordering of the disks matters greatly. */
-               /* FIX: Is this ordering of drives even remotely optimal? */
-               count = 0;
-               i = d0_idx;
-               do {
-                       ptrs[count++] = page_address(sh->dev[i].page);
-                       if (count <= disks-2 && !test_bit(R5_UPTODATE, &sh->dev[i].flags))
-                               printk("block %d/%d not uptodate on parity calc\n", i,count);
-                       i = raid6_next_disk(i, disks);
-               } while ( i != d0_idx );
-//             break;
-//     }
 
-       raid6_call.gen_syndrome(disks, STRIPE_SIZE, ptrs);
+/* handle_completed_write_requests
+ * any written block on an uptodate or failed drive can be returned.
+ * Note that if we 'wrote' to a failed drive, it will be UPTODATE, but
+ * never LOCKED, so we don't need to test 'failed' directly.
+ */
+static void handle_completed_write_requests(raid5_conf_t *conf,
+       struct stripe_head *sh, int disks, struct bio **return_bi)
+{
+       int i;
+       struct r5dev *dev;
 
-       switch(method) {
-       case RECONSTRUCT_WRITE:
-               set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-               set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags);
-               set_bit(R5_LOCKED,   &sh->dev[pd_idx].flags);
-               set_bit(R5_LOCKED,   &sh->dev[qd_idx].flags);
-               break;
-       case UPDATE_PARITY:
-               set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-               set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags);
-               break;
-       }
+       for (i = disks; i--; )
+               if (sh->dev[i].written) {
+                       dev = &sh->dev[i];
+                       if (!test_bit(R5_LOCKED, &dev->flags) &&
+                               test_bit(R5_UPTODATE, &dev->flags)) {
+                               /* We can return any write requests */
+                               struct bio *wbi, *wbi2;
+                               int bitmap_end = 0;
+                               pr_debug("Return write for disc %d\n", i);
+                               spin_lock_irq(&conf->device_lock);
+                               wbi = dev->written;
+                               dev->written = NULL;
+                               while (wbi && wbi->bi_sector <
+                                       dev->sector + STRIPE_SECTORS) {
+                                       wbi2 = r5_next_bio(wbi, dev->sector);
+                                       if (--wbi->bi_phys_segments == 0) {
+                                               md_write_end(conf->mddev);
+                                               wbi->bi_next = *return_bi;
+                                               *return_bi = wbi;
+                                       }
+                                       wbi = wbi2;
+                               }
+                               if (dev->towrite == NULL)
+                                       bitmap_end = 1;
+                               spin_unlock_irq(&conf->device_lock);
+                               if (bitmap_end)
+                                       bitmap_endwrite(conf->mddev->bitmap,
+                                                       sh->sector,
+                                                       STRIPE_SECTORS,
+                                        !test_bit(STRIPE_DEGRADED, &sh->state),
+                                                       0);
+                       }
+               }
 }
 
+static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
+               struct stripe_head *sh, struct stripe_head_state *s, int disks)
+{
+       int rmw = 0, rcw = 0, i;
+       for (i = disks; i--; ) {
+               /* would I have to read this buffer for read_modify_write */
+               struct r5dev *dev = &sh->dev[i];
+               if ((dev->towrite || i == sh->pd_idx) &&
+                   !test_bit(R5_LOCKED, &dev->flags) &&
+                   !(test_bit(R5_UPTODATE, &dev->flags) ||
+                     test_bit(R5_Wantcompute, &dev->flags))) {
+                       if (test_bit(R5_Insync, &dev->flags))
+                               rmw++;
+                       else
+                               rmw += 2*disks;  /* cannot read it */
+               }
+               /* Would I have to read this buffer for reconstruct_write */
+               if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
+                   !test_bit(R5_LOCKED, &dev->flags) &&
+                   !(test_bit(R5_UPTODATE, &dev->flags) ||
+                   test_bit(R5_Wantcompute, &dev->flags))) {
+                       if (test_bit(R5_Insync, &dev->flags)) rcw++;
+                       else
+                               rcw += 2*disks;
+               }
+       }
+       pr_debug("for sector %llu, rmw=%d rcw=%d\n",
+               (unsigned long long)sh->sector, rmw, rcw);
+       set_bit(STRIPE_HANDLE, &sh->state);
+       if (rmw < rcw && rmw > 0)
+               /* prefer read-modify-write, but need to get some data */
+               for (i = disks; i--; ) {
+                       struct r5dev *dev = &sh->dev[i];
+                       if ((dev->towrite || i == sh->pd_idx) &&
+                           !test_bit(R5_LOCKED, &dev->flags) &&
+                           !(test_bit(R5_UPTODATE, &dev->flags) ||
+                           test_bit(R5_Wantcompute, &dev->flags)) &&
+                           test_bit(R5_Insync, &dev->flags)) {
+                               if (
+                                 test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+                                       pr_debug("Read_old block "
+                                               "%d for r-m-w\n", i);
+                                       set_bit(R5_LOCKED, &dev->flags);
+                                       set_bit(R5_Wantread, &dev->flags);
+                                       if (!test_and_set_bit(
+                                               STRIPE_OP_IO, &sh->ops.pending))
+                                               sh->ops.count++;
+                                       s->locked++;
+                               } else {
+                                       set_bit(STRIPE_DELAYED, &sh->state);
+                                       set_bit(STRIPE_HANDLE, &sh->state);
+                               }
+                       }
+               }
+       if (rcw <= rmw && rcw > 0)
+               /* want reconstruct write, but need to get some data */
+               for (i = disks; i--; ) {
+                       struct r5dev *dev = &sh->dev[i];
+                       if (!test_bit(R5_OVERWRITE, &dev->flags) &&
+                           i != sh->pd_idx &&
+                           !test_bit(R5_LOCKED, &dev->flags) &&
+                           !(test_bit(R5_UPTODATE, &dev->flags) ||
+                           test_bit(R5_Wantcompute, &dev->flags)) &&
+                           test_bit(R5_Insync, &dev->flags)) {
+                               if (
+                                 test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+                                       pr_debug("Read_old block "
+                                               "%d for Reconstruct\n", i);
+                                       set_bit(R5_LOCKED, &dev->flags);
+                                       set_bit(R5_Wantread, &dev->flags);
+                                       if (!test_and_set_bit(
+                                               STRIPE_OP_IO, &sh->ops.pending))
+                                               sh->ops.count++;
+                                       s->locked++;
+                               } else {
+                                       set_bit(STRIPE_DELAYED, &sh->state);
+                                       set_bit(STRIPE_HANDLE, &sh->state);
+                               }
+                       }
+               }
+       /* now if nothing is locked, and if we have enough data,
+        * we can start a write request
+        */
+       /* since handle_stripe can be called at any time we need to handle the
+        * case where a compute block operation has been submitted and then a
+        * subsequent call wants to start a write request.  raid5_run_ops only
+        * handles the case where compute block and postxor are requested
+        * simultaneously.  If this is not the case then new writes need to be
+        * held off until the compute completes.
+        */
+       if ((s->req_compute ||
+           !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) &&
+               (s->locked == 0 && (rcw == 0 || rmw == 0) &&
+               !test_bit(STRIPE_BIT_DELAY, &sh->state)))
+               s->locked += handle_write_operations5(sh, rcw == 0, 0);
+}
 
-/* Compute one missing block */
-static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
+static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
+               struct stripe_head *sh, struct stripe_head_state *s,
+               struct r6_state *r6s, int disks)
 {
-       int i, count, disks = sh->disks;
-       void *ptr[MAX_XOR_BLOCKS], *p;
-       int pd_idx = sh->pd_idx;
-       int qd_idx = raid6_next_disk(pd_idx, disks);
+       int rcw = 0, must_compute = 0, pd_idx = sh->pd_idx, i;
+       int qd_idx = r6s->qd_idx;
+       for (i = disks; i--; ) {
+               struct r5dev *dev = &sh->dev[i];
+               /* Would I have to read this buffer for reconstruct_write */
+               if (!test_bit(R5_OVERWRITE, &dev->flags)
+                   && i != pd_idx && i != qd_idx
+                   && (!test_bit(R5_LOCKED, &dev->flags)
+                           ) &&
+                   !test_bit(R5_UPTODATE, &dev->flags)) {
+                       if (test_bit(R5_Insync, &dev->flags)) rcw++;
+                       else {
+                               pr_debug("raid6: must_compute: "
+                                       "disk %d flags=%#lx\n", i, dev->flags);
+                               must_compute++;
+                       }
+               }
+       }
+       pr_debug("for sector %llu, rcw=%d, must_compute=%d\n",
+              (unsigned long long)sh->sector, rcw, must_compute);
+       set_bit(STRIPE_HANDLE, &sh->state);
 
-       PRINTK("compute_block_1, stripe %llu, idx %d\n",
-               (unsigned long long)sh->sector, dd_idx);
+       if (rcw > 0)
+               /* want reconstruct write, but need to get some data */
+               for (i = disks; i--; ) {
+                       struct r5dev *dev = &sh->dev[i];
+                       if (!test_bit(R5_OVERWRITE, &dev->flags)
+                           && !(s->failed == 0 && (i == pd_idx || i == qd_idx))
+                           && !test_bit(R5_LOCKED, &dev->flags) &&
+                           !test_bit(R5_UPTODATE, &dev->flags) &&
+                           test_bit(R5_Insync, &dev->flags)) {
+                               if (
+                                 test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+                                       pr_debug("Read_old stripe %llu "
+                                               "block %d for Reconstruct\n",
+                                            (unsigned long long)sh->sector, i);
+                                       set_bit(R5_LOCKED, &dev->flags);
+                                       set_bit(R5_Wantread, &dev->flags);
+                                       s->locked++;
+                               } else {
+                                       pr_debug("Request delayed stripe %llu "
+                                               "block %d for Reconstruct\n",
+                                            (unsigned long long)sh->sector, i);
+                                       set_bit(STRIPE_DELAYED, &sh->state);
+                                       set_bit(STRIPE_HANDLE, &sh->state);
+                               }
+                       }
+               }
+       /* now if nothing is locked, and if we have enough data, we can start a
+        * write request
+        */
+       if (s->locked == 0 && rcw == 0 &&
+           !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
+               if (must_compute > 0) {
+                       /* We have failed blocks and need to compute them */
+                       switch (s->failed) {
+                       case 0:
+                               BUG();
+                       case 1:
+                               compute_block_1(sh, r6s->failed_num[0], 0);
+                               break;
+                       case 2:
+                               compute_block_2(sh, r6s->failed_num[0],
+                                               r6s->failed_num[1]);
+                               break;
+                       default: /* This request should have been failed? */
+                               BUG();
+                       }
+               }
 
-       if ( dd_idx == qd_idx ) {
-               /* We're actually computing the Q drive */
-               compute_parity6(sh, UPDATE_PARITY);
-       } else {
-               ptr[0] = page_address(sh->dev[dd_idx].page);
-               if (!nozero) memset(ptr[0], 0, STRIPE_SIZE);
-               count = 1;
-               for (i = disks ; i--; ) {
-                       if (i == dd_idx || i == qd_idx)
-                               continue;
-                       p = page_address(sh->dev[i].page);
-                       if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
-                               ptr[count++] = p;
-                       else
-                               printk("compute_block() %d, stripe %llu, %d"
-                                      " not present\n", dd_idx,
+               pr_debug("Computing parity for stripe %llu\n",
+                       (unsigned long long)sh->sector);
+               compute_parity6(sh, RECONSTRUCT_WRITE);
+               /* now every locked buffer is ready to be written */
+               for (i = disks; i--; )
+                       if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
+                               pr_debug("Writing stripe %llu block %d\n",
                                       (unsigned long long)sh->sector, i);
-
-                       check_xor();
+                               s->locked++;
+                               set_bit(R5_Wantwrite, &sh->dev[i].flags);
+                       }
+               /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
+               set_bit(STRIPE_INSYNC, &sh->state);
+
+               if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+                       atomic_dec(&conf->preread_active_stripes);
+                       if (atomic_read(&conf->preread_active_stripes) <
+                           IO_THRESHOLD)
+                               md_wakeup_thread(conf->mddev->thread);
                }
-               if (count != 1)
-                       xor_block(count, STRIPE_SIZE, ptr);
-               if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
-               else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
        }
 }
 
-/* Compute two missing blocks */
-static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
+static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
+                               struct stripe_head_state *s, int disks)
 {
-       int i, count, disks = sh->disks;
-       int pd_idx = sh->pd_idx;
-       int qd_idx = raid6_next_disk(pd_idx, disks);
-       int d0_idx = raid6_next_disk(qd_idx, disks);
-       int faila, failb;
-
-       /* faila and failb are disk numbers relative to d0_idx */
-       /* pd_idx become disks-2 and qd_idx become disks-1 */
-       faila = (dd_idx1 < d0_idx) ? dd_idx1+(disks-d0_idx) : dd_idx1-d0_idx;
-       failb = (dd_idx2 < d0_idx) ? dd_idx2+(disks-d0_idx) : dd_idx2-d0_idx;
-
-       BUG_ON(faila == failb);
-       if ( failb < faila ) { int tmp = faila; faila = failb; failb = tmp; }
-
-       PRINTK("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
-              (unsigned long long)sh->sector, dd_idx1, dd_idx2, faila, failb);
-
-       if ( failb == disks-1 ) {
-               /* Q disk is one of the missing disks */
-               if ( faila == disks-2 ) {
-                       /* Missing P+Q, just recompute */
-                       compute_parity6(sh, UPDATE_PARITY);
-                       return;
-               } else {
-                       /* We're missing D+Q; recompute D from P */
-                       compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1, 0);
-                       compute_parity6(sh, UPDATE_PARITY); /* Is this necessary? */
-                       return;
+       set_bit(STRIPE_HANDLE, &sh->state);
+       /* Take one of the following actions:
+        * 1/ start a check parity operation if (uptodate == disks)
+        * 2/ finish a check parity operation and act on the result
+        * 3/ skip to the writeback section if we previously
+        *    initiated a recovery operation
+        */
+       if (s->failed == 0 &&
+           !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
+               if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
+                       BUG_ON(s->uptodate != disks);
+                       clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
+                       sh->ops.count++;
+                       s->uptodate--;
+               } else if (
+                      test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) {
+                       clear_bit(STRIPE_OP_CHECK, &sh->ops.ack);
+                       clear_bit(STRIPE_OP_CHECK, &sh->ops.pending);
+
+                       if (sh->ops.zero_sum_result == 0)
+                               /* parity is correct (on disc,
+                                * not in buffer any more)
+                                */
+                               set_bit(STRIPE_INSYNC, &sh->state);
+                       else {
+                               conf->mddev->resync_mismatches +=
+                                       STRIPE_SECTORS;
+                               if (test_bit(
+                                    MD_RECOVERY_CHECK, &conf->mddev->recovery))
+                                       /* don't try to repair!! */
+                                       set_bit(STRIPE_INSYNC, &sh->state);
+                               else {
+                                       set_bit(STRIPE_OP_COMPUTE_BLK,
+                                               &sh->ops.pending);
+                                       set_bit(STRIPE_OP_MOD_REPAIR_PD,
+                                               &sh->ops.pending);
+                                       set_bit(R5_Wantcompute,
+                                               &sh->dev[sh->pd_idx].flags);
+                                       sh->ops.target = sh->pd_idx;
+                                       sh->ops.count++;
+                                       s->uptodate++;
+                               }
+                       }
                }
        }
 
-       /* We're missing D+P or D+D; build pointer table */
-       {
-               /**** FIX THIS: This could be very bad if disks is close to 256 ****/
-               void *ptrs[disks];
-
-               count = 0;
-               i = d0_idx;
-               do {
-                       ptrs[count++] = page_address(sh->dev[i].page);
-                       i = raid6_next_disk(i, disks);
-                       if (i != dd_idx1 && i != dd_idx2 &&
-                           !test_bit(R5_UPTODATE, &sh->dev[i].flags))
-                               printk("compute_2 with missing block %d/%d\n", count, i);
-               } while ( i != d0_idx );
+       /* check if we can clear a parity disk reconstruct */
+       if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
+               test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
 
-               if ( failb == disks-2 ) {
-                       /* We're missing D+P. */
-                       raid6_datap_recov(disks, STRIPE_SIZE, faila, ptrs);
-               } else {
-                       /* We're missing D+D. */
-                       raid6_2data_recov(disks, STRIPE_SIZE, faila, failb, ptrs);
-               }
+               clear_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending);
+               clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+               clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
+               clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+       }
 
-               /* Both the above update both missing blocks */
-               set_bit(R5_UPTODATE, &sh->dev[dd_idx1].flags);
-               set_bit(R5_UPTODATE, &sh->dev[dd_idx2].flags);
+       /* Wait for check parity and compute block operations to complete
+        * before write-back
+        */
+       if (!test_bit(STRIPE_INSYNC, &sh->state) &&
+               !test_bit(STRIPE_OP_CHECK, &sh->ops.pending) &&
+               !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) {
+               struct r5dev *dev;
+               /* either failed parity check, or recovery is happening */
+               if (s->failed == 0)
+                       s->failed_num = sh->pd_idx;
+               dev = &sh->dev[s->failed_num];
+               BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
+               BUG_ON(s->uptodate != disks);
+
+               set_bit(R5_LOCKED, &dev->flags);
+               set_bit(R5_Wantwrite, &dev->flags);
+               if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+                       sh->ops.count++;
+
+               clear_bit(STRIPE_DEGRADED, &sh->state);
+               s->locked++;
+               set_bit(STRIPE_INSYNC, &sh->state);
        }
 }
 
 
-
-/*
- * Each stripe/dev can have one or more bion attached.
- * toread/towrite point to the first in a chain.
- * The bi_next chain must be in order.
- */
-static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
+static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
+                               struct stripe_head_state *s,
+                               struct r6_state *r6s, struct page *tmp_page,
+                               int disks)
 {
-       struct bio **bip;
-       raid5_conf_t *conf = sh->raid_conf;
-       int firstwrite=0;
-
-       PRINTK("adding bh b#%llu to stripe s#%llu\n",
-               (unsigned long long)bi->bi_sector,
-               (unsigned long long)sh->sector);
+       int update_p = 0, update_q = 0;
+       struct r5dev *dev;
+       int pd_idx = sh->pd_idx;
+       int qd_idx = r6s->qd_idx;
 
+       set_bit(STRIPE_HANDLE, &sh->state);
 
-       spin_lock(&sh->lock);
-       spin_lock_irq(&conf->device_lock);
-       if (forwrite) {
-               bip = &sh->dev[dd_idx].towrite;
-               if (*bip == NULL && sh->dev[dd_idx].written == NULL)
-                       firstwrite = 1;
-       } else
-               bip = &sh->dev[dd_idx].toread;
-       while (*bip && (*bip)->bi_sector < bi->bi_sector) {
-               if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
-                       goto overlap;
-               bip = & (*bip)->bi_next;
-       }
-       if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
-               goto overlap;
+       BUG_ON(s->failed > 2);
+       BUG_ON(s->uptodate < disks);
+       /* Want to check and possibly repair P and Q.
+        * However there could be one 'failed' device, in which
+        * case we can only check one of them, possibly using the
+        * other to generate missing data
+        */
 
-       BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
-       if (*bip)
-               bi->bi_next = *bip;
-       *bip = bi;
-       bi->bi_phys_segments ++;
-       spin_unlock_irq(&conf->device_lock);
-       spin_unlock(&sh->lock);
+       /* If !tmp_page, we cannot do the calculations,
+        * but as we have set STRIPE_HANDLE, we will soon be called
+        * by stripe_handle with a tmp_page - just wait until then.
+        */
+       if (tmp_page) {
+               if (s->failed == r6s->q_failed) {
+                       /* The only possible failed device holds 'Q', so it
+                        * makes sense to check P (If anything else were failed,
+                        * we would have used P to recreate it).
+                        */
+                       compute_block_1(sh, pd_idx, 1);
+                       if (!page_is_zero(sh->dev[pd_idx].page)) {
+                               compute_block_1(sh, pd_idx, 0);
+                               update_p = 1;
+                       }
+               }
+               if (!r6s->q_failed && s->failed < 2) {
+                       /* q is not failed, and we didn't use it to generate
+                        * anything, so it makes sense to check it
+                        */
+                       memcpy(page_address(tmp_page),
+                              page_address(sh->dev[qd_idx].page),
+                              STRIPE_SIZE);
+                       compute_parity6(sh, UPDATE_PARITY);
+                       if (memcmp(page_address(tmp_page),
+                                  page_address(sh->dev[qd_idx].page),
+                                  STRIPE_SIZE) != 0) {
+                               clear_bit(STRIPE_INSYNC, &sh->state);
+                               update_q = 1;
+                       }
+               }
+               if (update_p || update_q) {
+                       conf->mddev->resync_mismatches += STRIPE_SECTORS;
+                       if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+                               /* don't try to repair!! */
+                               update_p = update_q = 0;
+               }
 
-       PRINTK("added bi b#%llu to stripe s#%llu, disk %d.\n",
-               (unsigned long long)bi->bi_sector,
-               (unsigned long long)sh->sector, dd_idx);
+               /* now write out any block on a failed drive,
+                * or P or Q if they need it
+                */
 
-       if (conf->mddev->bitmap && firstwrite) {
-               bitmap_startwrite(conf->mddev->bitmap, sh->sector,
-                                 STRIPE_SECTORS, 0);
-               sh->bm_seq = conf->seq_flush+1;
-               set_bit(STRIPE_BIT_DELAY, &sh->state);
-       }
+               if (s->failed == 2) {
+                       dev = &sh->dev[r6s->failed_num[1]];
+                       s->locked++;
+                       set_bit(R5_LOCKED, &dev->flags);
+                       set_bit(R5_Wantwrite, &dev->flags);
+               }
+               if (s->failed >= 1) {
+                       dev = &sh->dev[r6s->failed_num[0]];
+                       s->locked++;
+                       set_bit(R5_LOCKED, &dev->flags);
+                       set_bit(R5_Wantwrite, &dev->flags);
+               }
 
-       if (forwrite) {
-               /* check if page is covered */
-               sector_t sector = sh->dev[dd_idx].sector;
-               for (bi=sh->dev[dd_idx].towrite;
-                    sector < sh->dev[dd_idx].sector + STRIPE_SECTORS &&
-                            bi && bi->bi_sector <= sector;
-                    bi = r5_next_bio(bi, sh->dev[dd_idx].sector)) {
-                       if (bi->bi_sector + (bi->bi_size>>9) >= sector)
-                               sector = bi->bi_sector + (bi->bi_size>>9);
+               if (update_p) {
+                       dev = &sh->dev[pd_idx];
+                       s->locked++;
+                       set_bit(R5_LOCKED, &dev->flags);
+                       set_bit(R5_Wantwrite, &dev->flags);
                }
-               if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS)
-                       set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags);
-       }
-       return 1;
+               if (update_q) {
+                       dev = &sh->dev[qd_idx];
+                       s->locked++;
+                       set_bit(R5_LOCKED, &dev->flags);
+                       set_bit(R5_Wantwrite, &dev->flags);
+               }
+               clear_bit(STRIPE_DEGRADED, &sh->state);
 
- overlap:
-       set_bit(R5_Overlap, &sh->dev[dd_idx].flags);
-       spin_unlock_irq(&conf->device_lock);
-       spin_unlock(&sh->lock);
-       return 0;
+               set_bit(STRIPE_INSYNC, &sh->state);
+       }
 }
 
-static void end_reshape(raid5_conf_t *conf);
-
-static int page_is_zero(struct page *p)
+static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
+                               struct r6_state *r6s)
 {
-       char *a = page_address(p);
-       return ((*(u32*)a) == 0 &&
-               memcmp(a, a+4, STRIPE_SIZE-4)==0);
-}
+       int i;
 
-static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
-{
-       int sectors_per_chunk = conf->chunk_size >> 9;
-       int pd_idx, dd_idx;
-       int chunk_offset = sector_div(stripe, sectors_per_chunk);
+       /* We have read all the blocks in this stripe and now we need to
+        * copy some of them into a target stripe for expand.
+        */
+       struct dma_async_tx_descriptor *tx = NULL;
+       clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+       for (i = 0; i < sh->disks; i++)
+               if (i != sh->pd_idx && (r6s && i != r6s->qd_idx)) {
+                       int dd_idx, pd_idx, j;
+                       struct stripe_head *sh2;
+
+                       sector_t bn = compute_blocknr(sh, i);
+                       sector_t s = raid5_compute_sector(bn, conf->raid_disks,
+                                               conf->raid_disks -
+                                               conf->max_degraded, &dd_idx,
+                                               &pd_idx, conf);
+                       sh2 = get_active_stripe(conf, s, conf->raid_disks,
+                                               pd_idx, 1);
+                       if (sh2 == NULL)
+                               /* so far only the early blocks of this stripe
+                                * have been requested.  When later blocks
+                                * get requested, we will try again
+                                */
+                               continue;
+                       if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
+                          test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) {
+                               /* must have already done this block */
+                               release_stripe(sh2);
+                               continue;
+                       }
 
-       raid5_compute_sector(stripe * (disks - conf->max_degraded)
-                            *sectors_per_chunk + chunk_offset,
-                            disks, disks - conf->max_degraded,
-                            &dd_idx, &pd_idx, conf);
-       return pd_idx;
-}
+                       /* place all the copies on one channel */
+                       tx = async_memcpy(sh2->dev[dd_idx].page,
+                               sh->dev[i].page, 0, 0, STRIPE_SIZE,
+                               ASYNC_TX_DEP_ACK, tx, NULL, NULL);
+
+                       set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);
+                       set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);
+                       for (j = 0; j < conf->raid_disks; j++)
+                               if (j != sh2->pd_idx &&
+                                   (r6s && j != r6s->qd_idx) &&
+                                   !test_bit(R5_Expanded, &sh2->dev[j].flags))
+                                       break;
+                       if (j == conf->raid_disks) {
+                               set_bit(STRIPE_EXPAND_READY, &sh2->state);
+                               set_bit(STRIPE_HANDLE, &sh2->state);
+                       }
+                       release_stripe(sh2);
 
+                       /* done submitting copies, wait for them to complete */
+                       if (i + 1 >= sh->disks) {
+                               async_tx_ack(tx);
+                               dma_wait_for_async_tx(tx);
+                       }
+               }
+}
 
 /*
  * handle_stripe - do things to a stripe.
@@ -1339,81 +2603,70 @@ static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
  *    schedule a write of some buffers
  *    return confirmation of parity correctness
  *
- * Parity calculations are done inside the stripe lock
  * buffers are taken off read_list or write_list, and bh_cache buffers
  * get BH_Lock set before the stripe lock is released.
  *
  */
+
 static void handle_stripe5(struct stripe_head *sh)
 {
        raid5_conf_t *conf = sh->raid_conf;
-       int disks = sh->disks;
-       struct bio *return_bi= NULL;
-       struct bio *bi;
-       int i;
-       int syncing, expanding, expanded;
-       int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
-       int non_overwrite = 0;
-       int failed_num=0;
+       int disks = sh->disks, i;
+       struct bio *return_bi = NULL;
+       struct stripe_head_state s;
        struct r5dev *dev;
+       unsigned long pending = 0;
 
-       PRINTK("handling stripe %llu, cnt=%d, pd_idx=%d\n",
-               (unsigned long long)sh->sector, atomic_read(&sh->count),
-               sh->pd_idx);
+       memset(&s, 0, sizeof(s));
+       pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d "
+               "ops=%lx:%lx:%lx\n", (unsigned long long)sh->sector, sh->state,
+               atomic_read(&sh->count), sh->pd_idx,
+               sh->ops.pending, sh->ops.ack, sh->ops.complete);
 
        spin_lock(&sh->lock);
        clear_bit(STRIPE_HANDLE, &sh->state);
        clear_bit(STRIPE_DELAYED, &sh->state);
 
-       syncing = test_bit(STRIPE_SYNCING, &sh->state);
-       expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-       expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
+       s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
+       s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+       s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
        /* Now to look around and see what can be done */
 
        rcu_read_lock();
        for (i=disks; i--; ) {
                mdk_rdev_t *rdev;
-               dev = &sh->dev[i];
+               struct r5dev *dev = &sh->dev[i];
                clear_bit(R5_Insync, &dev->flags);
 
-               PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
-                       i, dev->flags, dev->toread, dev->towrite, dev->written);
-               /* maybe we can reply to a read */
-               if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
-                       struct bio *rbi, *rbi2;
-                       PRINTK("Return read for disc %d\n", i);
-                       spin_lock_irq(&conf->device_lock);
-                       rbi = dev->toread;
-                       dev->toread = NULL;
-                       if (test_and_clear_bit(R5_Overlap, &dev->flags))
-                               wake_up(&conf->wait_for_overlap);
-                       spin_unlock_irq(&conf->device_lock);
-                       while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
-                               copy_data(0, rbi, dev->page, dev->sector);
-                               rbi2 = r5_next_bio(rbi, dev->sector);
-                               spin_lock_irq(&conf->device_lock);
-                               if (--rbi->bi_phys_segments == 0) {
-                                       rbi->bi_next = return_bi;
-                                       return_bi = rbi;
-                               }
-                               spin_unlock_irq(&conf->device_lock);
-                               rbi = rbi2;
-                       }
-               }
+               pr_debug("check %d: state 0x%lx toread %p read %p write %p "
+                       "written %p\n", i, dev->flags, dev->toread, dev->read,
+                       dev->towrite, dev->written);
 
-               /* now count some things */
-               if (test_bit(R5_LOCKED, &dev->flags)) locked++;
-               if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
+               /* maybe we can request a biofill operation
+                *
+                * new wantfill requests are only permitted while
+                * STRIPE_OP_BIOFILL is clear
+                */
+               if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread &&
+                       !test_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
+                       set_bit(R5_Wantfill, &dev->flags);
 
-               
-               if (dev->toread) to_read++;
+               /* now count some things */
+               if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
+               if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
+               if (test_bit(R5_Wantcompute, &dev->flags)) s.compute++;
+
+               if (test_bit(R5_Wantfill, &dev->flags))
+                       s.to_fill++;
+               else if (dev->toread)
+                       s.to_read++;
                if (dev->towrite) {
-                       to_write++;
+                       s.to_write++;
                        if (!test_bit(R5_OVERWRITE, &dev->flags))
-                               non_overwrite++;
+                               s.non_overwrite++;
                }
-               if (dev->written) written++;
+               if (dev->written)
+                       s.written++;
                rdev = rcu_dereference(conf->disks[i].rdev);
                if (!rdev || !test_bit(In_sync, &rdev->flags)) {
                        /* The ReadError flag will just be confusing now */
@@ -1422,306 +2675,131 @@ static void handle_stripe5(struct stripe_head *sh)
                }
                if (!rdev || !test_bit(In_sync, &rdev->flags)
                    || test_bit(R5_ReadError, &dev->flags)) {
-                       failed++;
-                       failed_num = i;
+                       s.failed++;
+                       s.failed_num = i;
                } else
                        set_bit(R5_Insync, &dev->flags);
        }
        rcu_read_unlock();
-       PRINTK("locked=%d uptodate=%d to_read=%d"
+
+       if (s.to_fill && !test_and_set_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
+               sh->ops.count++;
+
+       pr_debug("locked=%d uptodate=%d to_read=%d"
                " to_write=%d failed=%d failed_num=%d\n",
-               locked, uptodate, to_read, to_write, failed, failed_num);
+               s.locked, s.uptodate, s.to_read, s.to_write,
+               s.failed, s.failed_num);
        /* check if the array has lost two devices and, if so, some requests might
         * need to be failed
         */
-       if (failed > 1 && to_read+to_write+written) {
-               for (i=disks; i--; ) {
-                       int bitmap_end = 0;
-
-                       if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-                               mdk_rdev_t *rdev;
-                               rcu_read_lock();
-                               rdev = rcu_dereference(conf->disks[i].rdev);
-                               if (rdev && test_bit(In_sync, &rdev->flags))
-                                       /* multiple read failures in one stripe */
-                                       md_error(conf->mddev, rdev);
-                               rcu_read_unlock();
-                       }
-
-                       spin_lock_irq(&conf->device_lock);
-                       /* fail all writes first */
-                       bi = sh->dev[i].towrite;
-                       sh->dev[i].towrite = NULL;
-                       if (bi) { to_write--; bitmap_end = 1; }
-
-                       if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-                               wake_up(&conf->wait_for_overlap);
-
-                       while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
-                               struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
-                               clear_bit(BIO_UPTODATE, &bi->bi_flags);
-                               if (--bi->bi_phys_segments == 0) {
-                                       md_write_end(conf->mddev);
-                                       bi->bi_next = return_bi;
-                                       return_bi = bi;
-                               }
-                               bi = nextbi;
-                       }
-                       /* and fail all 'written' */
-                       bi = sh->dev[i].written;
-                       sh->dev[i].written = NULL;
-                       if (bi) bitmap_end = 1;
-                       while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
-                               struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
-                               clear_bit(BIO_UPTODATE, &bi->bi_flags);
-                               if (--bi->bi_phys_segments == 0) {
-                                       md_write_end(conf->mddev);
-                                       bi->bi_next = return_bi;
-                                       return_bi = bi;
-                               }
-                               bi = bi2;
-                       }
-
-                       /* fail any reads if this device is non-operational */
-                       if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
-                           test_bit(R5_ReadError, &sh->dev[i].flags)) {
-                               bi = sh->dev[i].toread;
-                               sh->dev[i].toread = NULL;
-                               if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-                                       wake_up(&conf->wait_for_overlap);
-                               if (bi) to_read--;
-                               while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
-                                       struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
-                                       clear_bit(BIO_UPTODATE, &bi->bi_flags);
-                                       if (--bi->bi_phys_segments == 0) {
-                                               bi->bi_next = return_bi;
-                                               return_bi = bi;
-                                       }
-                                       bi = nextbi;
-                               }
-                       }
-                       spin_unlock_irq(&conf->device_lock);
-                       if (bitmap_end)
-                               bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-                                               STRIPE_SECTORS, 0, 0);
-               }
-       }
-       if (failed > 1 && syncing) {
+       if (s.failed > 1 && s.to_read+s.to_write+s.written)
+               handle_requests_to_failed_array(conf, sh, &s, disks,
+                                               &return_bi);
+       if (s.failed > 1 && s.syncing) {
                md_done_sync(conf->mddev, STRIPE_SECTORS,0);
                clear_bit(STRIPE_SYNCING, &sh->state);
-               syncing = 0;
+               s.syncing = 0;
        }
 
        /* might be able to return some write requests if the parity block
         * is safe, or on a failed drive
         */
        dev = &sh->dev[sh->pd_idx];
-       if ( written &&
-            ( (test_bit(R5_Insync, &dev->flags) && !test_bit(R5_LOCKED, &dev->flags) &&
-               test_bit(R5_UPTODATE, &dev->flags))
-              || (failed == 1 && failed_num == sh->pd_idx))
-           ) {
-           /* any written block on an uptodate or failed drive can be returned.
-            * Note that if we 'wrote' to a failed drive, it will be UPTODATE, but 
-            * never LOCKED, so we don't need to test 'failed' directly.
-            */
-           for (i=disks; i--; )
-               if (sh->dev[i].written) {
-                   dev = &sh->dev[i];
-                   if (!test_bit(R5_LOCKED, &dev->flags) &&
-                        test_bit(R5_UPTODATE, &dev->flags) ) {
-                       /* We can return any write requests */
-                           struct bio *wbi, *wbi2;
-                           int bitmap_end = 0;
-                           PRINTK("Return write for disc %d\n", i);
-                           spin_lock_irq(&conf->device_lock);
-                           wbi = dev->written;
-                           dev->written = NULL;
-                           while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
-                                   wbi2 = r5_next_bio(wbi, dev->sector);
-                                   if (--wbi->bi_phys_segments == 0) {
-                                           md_write_end(conf->mddev);
-                                           wbi->bi_next = return_bi;
-                                           return_bi = wbi;
-                                   }
-                                   wbi = wbi2;
-                           }
-                           if (dev->towrite == NULL)
-                                   bitmap_end = 1;
-                           spin_unlock_irq(&conf->device_lock);
-                           if (bitmap_end)
-                                   bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-                                                   STRIPE_SECTORS,
-                                                   !test_bit(STRIPE_DEGRADED, &sh->state), 0);
-                   }
-               }
-       }
+       if ( s.written &&
+            ((test_bit(R5_Insync, &dev->flags) &&
+              !test_bit(R5_LOCKED, &dev->flags) &&
+              test_bit(R5_UPTODATE, &dev->flags)) ||
+              (s.failed == 1 && s.failed_num == sh->pd_idx)))
+               handle_completed_write_requests(conf, sh, disks, &return_bi);
 
        /* Now we might consider reading some blocks, either to check/generate
         * parity, or to satisfy requests
         * or to load a block that is being partially written.
         */
-       if (to_read || non_overwrite || (syncing && (uptodate < disks)) || expanding) {
-               for (i=disks; i--;) {
-                       dev = &sh->dev[i];
-                       if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-                           (dev->toread ||
-                            (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
-                            syncing ||
-                            expanding ||
-                            (failed && (sh->dev[failed_num].toread ||
-                                        (sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num].flags))))
-                                   )
-                               ) {
-                               /* we would like to get this block, possibly
-                                * by computing it, but we might not be able to
-                                */
-                               if (uptodate == disks-1) {
-                                       PRINTK("Computing block %d\n", i);
-                                       compute_block(sh, i);
-                                       uptodate++;
-                               } else if (test_bit(R5_Insync, &dev->flags)) {
-                                       set_bit(R5_LOCKED, &dev->flags);
-                                       set_bit(R5_Wantread, &dev->flags);
-                                       locked++;
-                                       PRINTK("Reading block %d (sync=%d)\n", 
-                                               i, syncing);
-                               }
-                       }
-               }
-               set_bit(STRIPE_HANDLE, &sh->state);
+       if (s.to_read || s.non_overwrite ||
+           (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding ||
+           test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
+               handle_issuing_new_read_requests5(sh, &s, disks);
+
+       /* Now we check to see if any write operations have recently
+        * completed
+        */
+
+       /* leave prexor set until postxor is done, allows us to distinguish
+        * a rmw from a rcw during biodrain
+        */
+       if (test_bit(STRIPE_OP_PREXOR, &sh->ops.complete) &&
+               test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
+
+               clear_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
+               clear_bit(STRIPE_OP_PREXOR, &sh->ops.ack);
+               clear_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+
+               for (i = disks; i--; )
+                       clear_bit(R5_Wantprexor, &sh->dev[i].flags);
        }
 
-       /* now to consider writing and what else, if anything should be read */
-       if (to_write) {
-               int rmw=0, rcw=0;
-               for (i=disks ; i--;) {
-                       /* would I have to read this buffer for read_modify_write */
+       /* if only POSTXOR is set then this is an 'expand' postxor */
+       if (test_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete) &&
+               test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
+
+               clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
+               clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.ack);
+               clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+
+               clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+               clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
+               clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+
+               /* All the 'written' buffers and the parity block are ready to
+                * be written back to disk
+                */
+               BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
+               for (i = disks; i--; ) {
                        dev = &sh->dev[i];
-                       if ((dev->towrite || i == sh->pd_idx) &&
-                           (!test_bit(R5_LOCKED, &dev->flags) 
-                                   ) &&
-                           !test_bit(R5_UPTODATE, &dev->flags)) {
-                               if (test_bit(R5_Insync, &dev->flags)
-/*                                 && !(!mddev->insync && i == sh->pd_idx) */
-                                       )
-                                       rmw++;
-                               else rmw += 2*disks;  /* cannot read it */
-                       }
-                       /* Would I have to read this buffer for reconstruct_write */
-                       if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
-                           (!test_bit(R5_LOCKED, &dev->flags) 
-                                   ) &&
-                           !test_bit(R5_UPTODATE, &dev->flags)) {
-                               if (test_bit(R5_Insync, &dev->flags)) rcw++;
-                               else rcw += 2*disks;
+                       if (test_bit(R5_LOCKED, &dev->flags) &&
+                               (i == sh->pd_idx || dev->written)) {
+                               pr_debug("Writing block %d\n", i);
+                               set_bit(R5_Wantwrite, &dev->flags);
+                               if (!test_and_set_bit(
+                                   STRIPE_OP_IO, &sh->ops.pending))
+                                       sh->ops.count++;
+                               if (!test_bit(R5_Insync, &dev->flags) ||
+                                   (i == sh->pd_idx && s.failed == 0))
+                                       set_bit(STRIPE_INSYNC, &sh->state);
                        }
                }
-               PRINTK("for sector %llu, rmw=%d rcw=%d\n", 
-                       (unsigned long long)sh->sector, rmw, rcw);
-               set_bit(STRIPE_HANDLE, &sh->state);
-               if (rmw < rcw && rmw > 0)
-                       /* prefer read-modify-write, but need to get some data */
-                       for (i=disks; i--;) {
-                               dev = &sh->dev[i];
-                               if ((dev->towrite || i == sh->pd_idx) &&
-                                   !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-                                   test_bit(R5_Insync, &dev->flags)) {
-                                       if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-                                       {
-                                               PRINTK("Read_old block %d for r-m-w\n", i);
-                                               set_bit(R5_LOCKED, &dev->flags);
-                                               set_bit(R5_Wantread, &dev->flags);
-                                               locked++;
-                                       } else {
-                                               set_bit(STRIPE_DELAYED, &sh->state);
-                                               set_bit(STRIPE_HANDLE, &sh->state);
-                                       }
-                               }
-                       }
-               if (rcw <= rmw && rcw > 0)
-                       /* want reconstruct write, but need to get some data */
-                       for (i=disks; i--;) {
-                               dev = &sh->dev[i];
-                               if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
-                                   !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-                                   test_bit(R5_Insync, &dev->flags)) {
-                                       if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-                                       {
-                                               PRINTK("Read_old block %d for Reconstruct\n", i);
-                                               set_bit(R5_LOCKED, &dev->flags);
-                                               set_bit(R5_Wantread, &dev->flags);
-                                               locked++;
-                                       } else {
-                                               set_bit(STRIPE_DELAYED, &sh->state);
-                                               set_bit(STRIPE_HANDLE, &sh->state);
-                                       }
-                               }
-                       }
-               /* now if nothing is locked, and if we have enough data, we can start a write request */
-               if (locked == 0 && (rcw == 0 ||rmw == 0) &&
-                   !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
-                       PRINTK("Computing parity...\n");
-                       compute_parity5(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
-                       /* now every locked buffer is ready to be written */
-                       for (i=disks; i--;)
-                               if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
-                                       PRINTK("Writing block %d\n", i);
-                                       locked++;
-                                       set_bit(R5_Wantwrite, &sh->dev[i].flags);
-                                       if (!test_bit(R5_Insync, &sh->dev[i].flags)
-                                           || (i==sh->pd_idx && failed == 0))
-                                               set_bit(STRIPE_INSYNC, &sh->state);
-                               }
-                       if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-                               atomic_dec(&conf->preread_active_stripes);
-                               if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
-                                       md_wakeup_thread(conf->mddev->thread);
-                       }
+               if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+                       atomic_dec(&conf->preread_active_stripes);
+                       if (atomic_read(&conf->preread_active_stripes) <
+                               IO_THRESHOLD)
+                               md_wakeup_thread(conf->mddev->thread);
                }
        }
 
-       /* maybe we need to check and possibly fix the parity for this stripe
-        * Any reads will already have been scheduled, so we just see if enough data
-        * is available
+       /* Now to consider new write requests and what else, if anything
+        * should be read.  We do not handle new writes when:
+        * 1/ A 'write' operation (copy+xor) is already in flight.
+        * 2/ A 'check' operation is in flight, as it may clobber the parity
+        *    block.
         */
-       if (syncing && locked == 0 &&
-           !test_bit(STRIPE_INSYNC, &sh->state)) {
-               set_bit(STRIPE_HANDLE, &sh->state);
-               if (failed == 0) {
-                       BUG_ON(uptodate != disks);
-                       compute_parity5(sh, CHECK_PARITY);
-                       uptodate--;
-                       if (page_is_zero(sh->dev[sh->pd_idx].page)) {
-                               /* parity is correct (on disc, not in buffer any more) */
-                               set_bit(STRIPE_INSYNC, &sh->state);
-                       } else {
-                               conf->mddev->resync_mismatches += STRIPE_SECTORS;
-                               if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
-                                       /* don't try to repair!! */
-                                       set_bit(STRIPE_INSYNC, &sh->state);
-                               else {
-                                       compute_block(sh, sh->pd_idx);
-                                       uptodate++;
-                               }
-                       }
-               }
-               if (!test_bit(STRIPE_INSYNC, &sh->state)) {
-                       /* either failed parity check, or recovery is happening */
-                       if (failed==0)
-                               failed_num = sh->pd_idx;
-                       dev = &sh->dev[failed_num];
-                       BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
-                       BUG_ON(uptodate != disks);
+       if (s.to_write && !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending) &&
+                         !test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
+               handle_issuing_new_write_requests5(conf, sh, &s, disks);
 
-                       set_bit(R5_LOCKED, &dev->flags);
-                       set_bit(R5_Wantwrite, &dev->flags);
-                       clear_bit(STRIPE_DEGRADED, &sh->state);
-                       locked++;
-                       set_bit(STRIPE_INSYNC, &sh->state);
-               }
-       }
-       if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
+       /* maybe we need to check and possibly fix the parity for this stripe
+        * Any reads will already have been scheduled, so we just see if enough
+        * data is available.  The parity check is held off while parity
+        * dependent operations are in flight.
+        */
+       if ((s.syncing && s.locked == 0 &&
+            !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
+            !test_bit(STRIPE_INSYNC, &sh->state)) ||
+             test_bit(STRIPE_OP_CHECK, &sh->ops.pending) ||
+             test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending))
+               handle_parity_checks5(conf, sh, &s, disks);
+
+       if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
                md_done_sync(conf->mddev, STRIPE_SECTORS,1);
                clear_bit(STRIPE_SYNCING, &sh->state);
        }
@@ -1729,186 +2807,102 @@ static void handle_stripe5(struct stripe_head *sh)
        /* If the failed drive is just a ReadError, then we might need to progress
         * the repair/check process
         */
-       if (failed == 1 && ! conf->mddev->ro &&
-           test_bit(R5_ReadError, &sh->dev[failed_num].flags)
-           && !test_bit(R5_LOCKED, &sh->dev[failed_num].flags)
-           && test_bit(R5_UPTODATE, &sh->dev[failed_num].flags)
+       if (s.failed == 1 && !conf->mddev->ro &&
+           test_bit(R5_ReadError, &sh->dev[s.failed_num].flags)
+           && !test_bit(R5_LOCKED, &sh->dev[s.failed_num].flags)
+           && test_bit(R5_UPTODATE, &sh->dev[s.failed_num].flags)
                ) {
-               dev = &sh->dev[failed_num];
+               dev = &sh->dev[s.failed_num];
                if (!test_bit(R5_ReWrite, &dev->flags)) {
                        set_bit(R5_Wantwrite, &dev->flags);
+                       if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+                               sh->ops.count++;
                        set_bit(R5_ReWrite, &dev->flags);
                        set_bit(R5_LOCKED, &dev->flags);
-                       locked++;
+                       s.locked++;
                } else {
                        /* let's read it back */
                        set_bit(R5_Wantread, &dev->flags);
+                       if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+                               sh->ops.count++;
                        set_bit(R5_LOCKED, &dev->flags);
-                       locked++;
+                       s.locked++;
                }
        }
 
-       if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
-               /* Need to write out all blocks after computing parity */
-               sh->disks = conf->raid_disks;
-               sh->pd_idx = stripe_to_pdidx(sh->sector, conf, conf->raid_disks);
-               compute_parity5(sh, RECONSTRUCT_WRITE);
-               for (i= conf->raid_disks; i--;) {
-                       set_bit(R5_LOCKED, &sh->dev[i].flags);
-                       locked++;
+       /* Finish postxor operations initiated by the expansion
+        * process
+        */
+       if (test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete) &&
+               !test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending)) {
+
+               clear_bit(STRIPE_EXPANDING, &sh->state);
+
+               clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+               clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
+               clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+
+               for (i = conf->raid_disks; i--; ) {
                        set_bit(R5_Wantwrite, &sh->dev[i].flags);
+                       if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+                               sh->ops.count++;
                }
-               clear_bit(STRIPE_EXPANDING, &sh->state);
-       } else if (expanded) {
+       }
+
+       if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) &&
+               !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+               /* Need to write out all blocks after computing parity */
+               sh->disks = conf->raid_disks;
+               sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
+                       conf->raid_disks);
+               s.locked += handle_write_operations5(sh, 0, 1);
+       } else if (s.expanded &&
+               !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
                clear_bit(STRIPE_EXPAND_READY, &sh->state);
                atomic_dec(&conf->reshape_stripes);
                wake_up(&conf->wait_for_overlap);
                md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
        }
 
-       if (expanding && locked == 0) {
-               /* We have read all the blocks in this stripe and now we need to
-                * copy some of them into a target stripe for expand.
-                */
-               clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-               for (i=0; i< sh->disks; i++)
-                       if (i != sh->pd_idx) {
-                               int dd_idx, pd_idx, j;
-                               struct stripe_head *sh2;
-
-                               sector_t bn = compute_blocknr(sh, i);
-                               sector_t s = raid5_compute_sector(bn, conf->raid_disks,
-                                                                 conf->raid_disks-1,
-                                                                 &dd_idx, &pd_idx, conf);
-                               sh2 = get_active_stripe(conf, s, conf->raid_disks, pd_idx, 1);
-                               if (sh2 == NULL)
-                                       /* so far only the early blocks of this stripe
-                                        * have been requested.  When later blocks
-                                        * get requested, we will try again
-                                        */
-                                       continue;
-                               if(!test_bit(STRIPE_EXPANDING, &sh2->state) ||
-                                  test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) {
-                                       /* must have already done this block */
-                                       release_stripe(sh2);
-                                       continue;
-                               }
-                               memcpy(page_address(sh2->dev[dd_idx].page),
-                                      page_address(sh->dev[i].page),
-                                      STRIPE_SIZE);
-                               set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);
-                               set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);
-                               for (j=0; j<conf->raid_disks; j++)
-                                       if (j != sh2->pd_idx &&
-                                           !test_bit(R5_Expanded, &sh2->dev[j].flags))
-                                               break;
-                               if (j == conf->raid_disks) {
-                                       set_bit(STRIPE_EXPAND_READY, &sh2->state);
-                                       set_bit(STRIPE_HANDLE, &sh2->state);
-                               }
-                               release_stripe(sh2);
-                       }
-       }
+       if (s.expanding && s.locked == 0)
+               handle_stripe_expansion(conf, sh, NULL);
+
+       if (sh->ops.count)
+               pending = get_stripe_work(sh);
 
        spin_unlock(&sh->lock);
 
-       while ((bi=return_bi)) {
-               int bytes = bi->bi_size;
+       if (pending)
+               raid5_run_ops(sh, pending);
 
-               return_bi = bi->bi_next;
-               bi->bi_next = NULL;
-               bi->bi_size = 0;
-               bi->bi_end_io(bi, bytes,
-                             test_bit(BIO_UPTODATE, &bi->bi_flags)
-                               ? 0 : -EIO);
-       }
-       for (i=disks; i-- ;) {
-               int rw;
-               struct bio *bi;
-               mdk_rdev_t *rdev;
-               if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
-                       rw = WRITE;
-               else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
-                       rw = READ;
-               else
-                       continue;
-               bi = &sh->dev[i].req;
-               bi->bi_rw = rw;
-               if (rw == WRITE)
-                       bi->bi_end_io = raid5_end_write_request;
-               else
-                       bi->bi_end_io = raid5_end_read_request;
-               rcu_read_lock();
-               rdev = rcu_dereference(conf->disks[i].rdev);
-               if (rdev && test_bit(Faulty, &rdev->flags))
-                       rdev = NULL;
-               if (rdev)
-                       atomic_inc(&rdev->nr_pending);
-               rcu_read_unlock();
-               if (rdev) {
-                       if (syncing || expanding || expanded)
-                               md_sync_acct(rdev->bdev, STRIPE_SECTORS);
+       return_io(return_bi);
 
-                       bi->bi_bdev = rdev->bdev;
-                       PRINTK("for %llu schedule op %ld on disc %d\n",
-                               (unsigned long long)sh->sector, bi->bi_rw, i);
-                       atomic_inc(&sh->count);
-                       bi->bi_sector = sh->sector + rdev->data_offset;
-                       bi->bi_flags = 1 << BIO_UPTODATE;
-                       bi->bi_vcnt = 1;        
-                       bi->bi_max_vecs = 1;
-                       bi->bi_idx = 0;
-                       bi->bi_io_vec = &sh->dev[i].vec;
-                       bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
-                       bi->bi_io_vec[0].bv_offset = 0;
-                       bi->bi_size = STRIPE_SIZE;
-                       bi->bi_next = NULL;
-                       if (rw == WRITE &&
-                           test_bit(R5_ReWrite, &sh->dev[i].flags))
-                               atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
-                       generic_make_request(bi);
-               } else {
-                       if (rw == WRITE)
-                               set_bit(STRIPE_DEGRADED, &sh->state);
-                       PRINTK("skip op %ld on disc %d for sector %llu\n",
-                               bi->bi_rw, i, (unsigned long long)sh->sector);
-                       clear_bit(R5_LOCKED, &sh->dev[i].flags);
-                       set_bit(STRIPE_HANDLE, &sh->state);
-               }
-       }
 }
 
 static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
 {
        raid6_conf_t *conf = sh->raid_conf;
        int disks = sh->disks;
-       struct bio *return_bi= NULL;
-       struct bio *bi;
-       int i;
-       int syncing, expanding, expanded;
-       int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
-       int non_overwrite = 0;
-       int failed_num[2] = {0, 0};
+       struct bio *return_bi = NULL;
+       int i, pd_idx = sh->pd_idx;
+       struct stripe_head_state s;
+       struct r6_state r6s;
        struct r5dev *dev, *pdev, *qdev;
-       int pd_idx = sh->pd_idx;
-       int qd_idx = raid6_next_disk(pd_idx, disks);
-       int p_failed, q_failed;
 
-       PRINTK("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d, qd_idx=%d\n",
-              (unsigned long long)sh->sector, sh->state, atomic_read(&sh->count),
-              pd_idx, qd_idx);
+       r6s.qd_idx = raid6_next_disk(pd_idx, disks);
+       pr_debug("handling stripe %llu, state=%#lx cnt=%d, "
+               "pd_idx=%d, qd_idx=%d\n",
+              (unsigned long long)sh->sector, sh->state,
+              atomic_read(&sh->count), pd_idx, r6s.qd_idx);
+       memset(&s, 0, sizeof(s));
 
        spin_lock(&sh->lock);
        clear_bit(STRIPE_HANDLE, &sh->state);
        clear_bit(STRIPE_DELAYED, &sh->state);
 
-       syncing = test_bit(STRIPE_SYNCING, &sh->state);
-       expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-       expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
+       s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
+       s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+       s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
        /* Now to look around and see what can be done */
 
        rcu_read_lock();
@@ -1917,12 +2911,12 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                dev = &sh->dev[i];
                clear_bit(R5_Insync, &dev->flags);
 
-               PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
+               pr_debug("check %d: state 0x%lx read %p write %p written %p\n",
                        i, dev->flags, dev->toread, dev->towrite, dev->written);
                /* maybe we can reply to a read */
                if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
                        struct bio *rbi, *rbi2;
-                       PRINTK("Return read for disc %d\n", i);
+                       pr_debug("Return read for disc %d\n", i);
                        spin_lock_irq(&conf->device_lock);
                        rbi = dev->toread;
                        dev->toread = NULL;
@@ -1943,17 +2937,19 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                }
 
                /* now count some things */
-               if (test_bit(R5_LOCKED, &dev->flags)) locked++;
-               if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
+               if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
+               if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
 
 
-               if (dev->toread) to_read++;
+               if (dev->toread)
+                       s.to_read++;
                if (dev->towrite) {
-                       to_write++;
+                       s.to_write++;
                        if (!test_bit(R5_OVERWRITE, &dev->flags))
-                               non_overwrite++;
+                               s.non_overwrite++;
                }
-               if (dev->written) written++;
+               if (dev->written)
+                       s.written++;
                rdev = rcu_dereference(conf->disks[i].rdev);
                if (!rdev || !test_bit(In_sync, &rdev->flags)) {
                        /* The ReadError flag will just be confusing now */
@@ -1962,96 +2958,27 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                }
                if (!rdev || !test_bit(In_sync, &rdev->flags)
                    || test_bit(R5_ReadError, &dev->flags)) {
-                       if ( failed < 2 )
-                               failed_num[failed] = i;
-                       failed++;
+                       if (s.failed < 2)
+                               r6s.failed_num[s.failed] = i;
+                       s.failed++;
                } else
                        set_bit(R5_Insync, &dev->flags);
        }
        rcu_read_unlock();
-       PRINTK("locked=%d uptodate=%d to_read=%d"
+       pr_debug("locked=%d uptodate=%d to_read=%d"
               " to_write=%d failed=%d failed_num=%d,%d\n",
-              locked, uptodate, to_read, to_write, failed,
-              failed_num[0], failed_num[1]);
-       /* check if the array has lost >2 devices and, if so, some requests might
-        * need to be failed
+              s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
+              r6s.failed_num[0], r6s.failed_num[1]);
+       /* check if the array has lost >2 devices and, if so, some requests
+        * might need to be failed
         */
-       if (failed > 2 && to_read+to_write+written) {
-               for (i=disks; i--; ) {
-                       int bitmap_end = 0;
-
-                       if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-                               mdk_rdev_t *rdev;
-                               rcu_read_lock();
-                               rdev = rcu_dereference(conf->disks[i].rdev);
-                               if (rdev && test_bit(In_sync, &rdev->flags))
-                                       /* multiple read failures in one stripe */
-                                       md_error(conf->mddev, rdev);
-                               rcu_read_unlock();
-                       }
-
-                       spin_lock_irq(&conf->device_lock);
-                       /* fail all writes first */
-                       bi = sh->dev[i].towrite;
-                       sh->dev[i].towrite = NULL;
-                       if (bi) { to_write--; bitmap_end = 1; }
-
-                       if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-                               wake_up(&conf->wait_for_overlap);
-
-                       while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
-                               struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
-                               clear_bit(BIO_UPTODATE, &bi->bi_flags);
-                               if (--bi->bi_phys_segments == 0) {
-                                       md_write_end(conf->mddev);
-                                       bi->bi_next = return_bi;
-                                       return_bi = bi;
-                               }
-                               bi = nextbi;
-                       }
-                       /* and fail all 'written' */
-                       bi = sh->dev[i].written;
-                       sh->dev[i].written = NULL;
-                       if (bi) bitmap_end = 1;
-                       while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
-                               struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
-                               clear_bit(BIO_UPTODATE, &bi->bi_flags);
-                               if (--bi->bi_phys_segments == 0) {
-                                       md_write_end(conf->mddev);
-                                       bi->bi_next = return_bi;
-                                       return_bi = bi;
-                               }
-                               bi = bi2;
-                       }
-
-                       /* fail any reads if this device is non-operational */
-                       if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
-                           test_bit(R5_ReadError, &sh->dev[i].flags)) {
-                               bi = sh->dev[i].toread;
-                               sh->dev[i].toread = NULL;
-                               if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-                                       wake_up(&conf->wait_for_overlap);
-                               if (bi) to_read--;
-                               while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
-                                       struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
-                                       clear_bit(BIO_UPTODATE, &bi->bi_flags);
-                                       if (--bi->bi_phys_segments == 0) {
-                                               bi->bi_next = return_bi;
-                                               return_bi = bi;
-                                       }
-                                       bi = nextbi;
-                               }
-                       }
-                       spin_unlock_irq(&conf->device_lock);
-                       if (bitmap_end)
-                               bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-                                               STRIPE_SECTORS, 0, 0);
-               }
-       }
-       if (failed > 2 && syncing) {
+       if (s.failed > 2 && s.to_read+s.to_write+s.written)
+               handle_requests_to_failed_array(conf, sh, &s, disks,
+                                               &return_bi);
+       if (s.failed > 2 && s.syncing) {
                md_done_sync(conf->mddev, STRIPE_SECTORS,0);
                clear_bit(STRIPE_SYNCING, &sh->state);
-               syncing = 0;
+               s.syncing = 0;
        }
 
        /*
@@ -2059,279 +2986,41 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
         * are safe, or on a failed drive
         */
        pdev = &sh->dev[pd_idx];
-       p_failed = (failed >= 1 && failed_num[0] == pd_idx)
-               || (failed >= 2 && failed_num[1] == pd_idx);
-       qdev = &sh->dev[qd_idx];
-       q_failed = (failed >= 1 && failed_num[0] == qd_idx)
-               || (failed >= 2 && failed_num[1] == qd_idx);
-
-       if ( written &&
-            ( p_failed || ((test_bit(R5_Insync, &pdev->flags)
+       r6s.p_failed = (s.failed >= 1 && r6s.failed_num[0] == pd_idx)
+               || (s.failed >= 2 && r6s.failed_num[1] == pd_idx);
+       qdev = &sh->dev[r6s.qd_idx];
+       r6s.q_failed = (s.failed >= 1 && r6s.failed_num[0] == r6s.qd_idx)
+               || (s.failed >= 2 && r6s.failed_num[1] == r6s.qd_idx);
+
+       if ( s.written &&
+            ( r6s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
                             && !test_bit(R5_LOCKED, &pdev->flags)
-                            && test_bit(R5_UPTODATE, &pdev->flags))) ) &&
-            ( q_failed || ((test_bit(R5_Insync, &qdev->flags)
+                            && test_bit(R5_UPTODATE, &pdev->flags)))) &&
+            ( r6s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
                             && !test_bit(R5_LOCKED, &qdev->flags)
-                            && test_bit(R5_UPTODATE, &qdev->flags))) ) ) {
-               /* any written block on an uptodate or failed drive can be
-                * returned.  Note that if we 'wrote' to a failed drive,
-                * it will be UPTODATE, but never LOCKED, so we don't need
-                * to test 'failed' directly.
-                */
-               for (i=disks; i--; )
-                       if (sh->dev[i].written) {
-                               dev = &sh->dev[i];
-                               if (!test_bit(R5_LOCKED, &dev->flags) &&
-                                   test_bit(R5_UPTODATE, &dev->flags) ) {
-                                       /* We can return any write requests */
-                                       int bitmap_end = 0;
-                                       struct bio *wbi, *wbi2;
-                                       PRINTK("Return write for stripe %llu disc %d\n",
-                                              (unsigned long long)sh->sector, i);
-                                       spin_lock_irq(&conf->device_lock);
-                                       wbi = dev->written;
-                                       dev->written = NULL;
-                                       while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
-                                               wbi2 = r5_next_bio(wbi, dev->sector);
-                                               if (--wbi->bi_phys_segments == 0) {
-                                                       md_write_end(conf->mddev);
-                                                       wbi->bi_next = return_bi;
-                                                       return_bi = wbi;
-                                               }
-                                               wbi = wbi2;
-                                       }
-                                       if (dev->towrite == NULL)
-                                               bitmap_end = 1;
-                                       spin_unlock_irq(&conf->device_lock);
-                                       if (bitmap_end)
-                                               bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-                                                               STRIPE_SECTORS,
-                                                               !test_bit(STRIPE_DEGRADED, &sh->state), 0);
-                               }
-                       }
-       }
+                            && test_bit(R5_UPTODATE, &qdev->flags)))))
+               handle_completed_write_requests(conf, sh, disks, &return_bi);
 
        /* Now we might consider reading some blocks, either to check/generate
         * parity, or to satisfy requests
         * or to load a block that is being partially written.
         */
-       if (to_read || non_overwrite || (to_write && failed) ||
-           (syncing && (uptodate < disks)) || expanding) {
-               for (i=disks; i--;) {
-                       dev = &sh->dev[i];
-                       if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-                           (dev->toread ||
-                            (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
-                            syncing ||
-                            expanding ||
-                            (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) ||
-                            (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write))
-                                   )
-                               ) {
-                               /* we would like to get this block, possibly
-                                * by computing it, but we might not be able to
-                                */
-                               if (uptodate == disks-1) {
-                                       PRINTK("Computing stripe %llu block %d\n",
-                                              (unsigned long long)sh->sector, i);
-                                       compute_block_1(sh, i, 0);
-                                       uptodate++;
-                               } else if ( uptodate == disks-2 && failed >= 2 ) {
-                                       /* Computing 2-failure is *very* expensive; only do it if failed >= 2 */
-                                       int other;
-                                       for (other=disks; other--;) {
-                                               if ( other == i )
-                                                       continue;
-                                               if ( !test_bit(R5_UPTODATE, &sh->dev[other].flags) )
-                                                       break;
-                                       }
-                                       BUG_ON(other < 0);
-                                       PRINTK("Computing stripe %llu blocks %d,%d\n",
-                                              (unsigned long long)sh->sector, i, other);
-                                       compute_block_2(sh, i, other);
-                                       uptodate += 2;
-                               } else if (test_bit(R5_Insync, &dev->flags)) {
-                                       set_bit(R5_LOCKED, &dev->flags);
-                                       set_bit(R5_Wantread, &dev->flags);
-                                       locked++;
-                                       PRINTK("Reading block %d (sync=%d)\n",
-                                               i, syncing);
-                               }
-                       }
-               }
-               set_bit(STRIPE_HANDLE, &sh->state);
-       }
+       if (s.to_read || s.non_overwrite || (s.to_write && s.failed) ||
+           (s.syncing && (s.uptodate < disks)) || s.expanding)
+               handle_issuing_new_read_requests6(sh, &s, &r6s, disks);
 
        /* now to consider writing and what else, if anything should be read */
-       if (to_write) {
-               int rcw=0, must_compute=0;
-               for (i=disks ; i--;) {
-                       dev = &sh->dev[i];
-                       /* Would I have to read this buffer for reconstruct_write */
-                       if (!test_bit(R5_OVERWRITE, &dev->flags)
-                           && i != pd_idx && i != qd_idx
-                           && (!test_bit(R5_LOCKED, &dev->flags)
-                                   ) &&
-                           !test_bit(R5_UPTODATE, &dev->flags)) {
-                               if (test_bit(R5_Insync, &dev->flags)) rcw++;
-                               else {
-                                       PRINTK("raid6: must_compute: disk %d flags=%#lx\n", i, dev->flags);
-                                       must_compute++;
-                               }
-                       }
-               }
-               PRINTK("for sector %llu, rcw=%d, must_compute=%d\n",
-                      (unsigned long long)sh->sector, rcw, must_compute);
-               set_bit(STRIPE_HANDLE, &sh->state);
-
-               if (rcw > 0)
-                       /* want reconstruct write, but need to get some data */
-                       for (i=disks; i--;) {
-                               dev = &sh->dev[i];
-                               if (!test_bit(R5_OVERWRITE, &dev->flags)
-                                   && !(failed == 0 && (i == pd_idx || i == qd_idx))
-                                   && !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-                                   test_bit(R5_Insync, &dev->flags)) {
-                                       if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-                                       {
-                                               PRINTK("Read_old stripe %llu block %d for Reconstruct\n",
-                                                      (unsigned long long)sh->sector, i);
-                                               set_bit(R5_LOCKED, &dev->flags);
-                                               set_bit(R5_Wantread, &dev->flags);
-                                               locked++;
-                                       } else {
-                                               PRINTK("Request delayed stripe %llu block %d for Reconstruct\n",
-                                                      (unsigned long long)sh->sector, i);
-                                               set_bit(STRIPE_DELAYED, &sh->state);
-                                               set_bit(STRIPE_HANDLE, &sh->state);
-                                       }
-                               }
-                       }
-               /* now if nothing is locked, and if we have enough data, we can start a write request */
-               if (locked == 0 && rcw == 0 &&
-                   !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
-                       if ( must_compute > 0 ) {
-                               /* We have failed blocks and need to compute them */
-                               switch ( failed ) {
-                               case 0: BUG();
-                               case 1: compute_block_1(sh, failed_num[0], 0); break;
-                               case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break;
-                               default: BUG(); /* This request should have been failed? */
-                               }
-                       }
-
-                       PRINTK("Computing parity for stripe %llu\n", (unsigned long long)sh->sector);
-                       compute_parity6(sh, RECONSTRUCT_WRITE);
-                       /* now every locked buffer is ready to be written */
-                       for (i=disks; i--;)
-                               if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
-                                       PRINTK("Writing stripe %llu block %d\n",
-                                              (unsigned long long)sh->sector, i);
-                                       locked++;
-                                       set_bit(R5_Wantwrite, &sh->dev[i].flags);
-                               }
-                       /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
-                       set_bit(STRIPE_INSYNC, &sh->state);
-
-                       if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-                               atomic_dec(&conf->preread_active_stripes);
-                               if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
-                                       md_wakeup_thread(conf->mddev->thread);
-                       }
-               }
-       }
+       if (s.to_write)
+               handle_issuing_new_write_requests6(conf, sh, &s, &r6s, disks);
 
        /* maybe we need to check and possibly fix the parity for this stripe
-        * Any reads will already have been scheduled, so we just see if enough data
-        * is available
+        * Any reads will already have been scheduled, so we just see if enough
+        * data is available
         */
-       if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) {
-               int update_p = 0, update_q = 0;
-               struct r5dev *dev;
-
-               set_bit(STRIPE_HANDLE, &sh->state);
-
-               BUG_ON(failed>2);
-               BUG_ON(uptodate < disks);
-               /* Want to check and possibly repair P and Q.
-                * However there could be one 'failed' device, in which
-                * case we can only check one of them, possibly using the
-                * other to generate missing data
-                */
-
-               /* If !tmp_page, we cannot do the calculations,
-                * but as we have set STRIPE_HANDLE, we will soon be called
-                * by stripe_handle with a tmp_page - just wait until then.
-                */
-               if (tmp_page) {
-                       if (failed == q_failed) {
-                               /* The only possible failed device holds 'Q', so it makes
-                                * sense to check P (If anything else were failed, we would
-                                * have used P to recreate it).
-                                */
-                               compute_block_1(sh, pd_idx, 1);
-                               if (!page_is_zero(sh->dev[pd_idx].page)) {
-                                       compute_block_1(sh,pd_idx,0);
-                                       update_p = 1;
-                               }
-                       }
-                       if (!q_failed && failed < 2) {
-                               /* q is not failed, and we didn't use it to generate
-                                * anything, so it makes sense to check it
-                                */
-                               memcpy(page_address(tmp_page),
-                                      page_address(sh->dev[qd_idx].page),
-                                      STRIPE_SIZE);
-                               compute_parity6(sh, UPDATE_PARITY);
-                               if (memcmp(page_address(tmp_page),
-                                          page_address(sh->dev[qd_idx].page),
-                                          STRIPE_SIZE)!= 0) {
-                                       clear_bit(STRIPE_INSYNC, &sh->state);
-                                       update_q = 1;
-                               }
-                       }
-                       if (update_p || update_q) {
-                               conf->mddev->resync_mismatches += STRIPE_SECTORS;
-                               if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
-                                       /* don't try to repair!! */
-                                       update_p = update_q = 0;
-                       }
-
-                       /* now write out any block on a failed drive,
-                        * or P or Q if they need it
-                        */
-
-                       if (failed == 2) {
-                               dev = &sh->dev[failed_num[1]];
-                               locked++;
-                               set_bit(R5_LOCKED, &dev->flags);
-                               set_bit(R5_Wantwrite, &dev->flags);
-                       }
-                       if (failed >= 1) {
-                               dev = &sh->dev[failed_num[0]];
-                               locked++;
-                               set_bit(R5_LOCKED, &dev->flags);
-                               set_bit(R5_Wantwrite, &dev->flags);
-                       }
-
-                       if (update_p) {
-                               dev = &sh->dev[pd_idx];
-                               locked ++;
-                               set_bit(R5_LOCKED, &dev->flags);
-                               set_bit(R5_Wantwrite, &dev->flags);
-                       }
-                       if (update_q) {
-                               dev = &sh->dev[qd_idx];
-                               locked++;
-                               set_bit(R5_LOCKED, &dev->flags);
-                               set_bit(R5_Wantwrite, &dev->flags);
-                       }
-                       clear_bit(STRIPE_DEGRADED, &sh->state);
+       if (s.syncing && s.locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state))
+               handle_parity_checks6(conf, sh, &s, &r6s, tmp_page, disks);
 
-                       set_bit(STRIPE_INSYNC, &sh->state);
-               }
-       }
-
-       if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
+       if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
                md_done_sync(conf->mddev, STRIPE_SECTORS,1);
                clear_bit(STRIPE_SYNCING, &sh->state);
        }
@@ -2339,9 +3028,9 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
        /* If the failed drives are just a ReadError, then we might need
         * to progress the repair/check process
         */
-       if (failed <= 2 && ! conf->mddev->ro)
-               for (i=0; i<failed;i++) {
-                       dev = &sh->dev[failed_num[i]];
+       if (s.failed <= 2 && !conf->mddev->ro)
+               for (i = 0; i < s.failed; i++) {
+                       dev = &sh->dev[r6s.failed_num[i]];
                        if (test_bit(R5_ReadError, &dev->flags)
                            && !test_bit(R5_LOCKED, &dev->flags)
                            && test_bit(R5_UPTODATE, &dev->flags)
@@ -2358,7 +3047,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                        }
                }
 
-       if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
+       if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
                /* Need to write out all blocks after computing P&Q */
                sh->disks = conf->raid_disks;
                sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
@@ -2366,82 +3055,24 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                compute_parity6(sh, RECONSTRUCT_WRITE);
                for (i = conf->raid_disks ; i-- ;  ) {
                        set_bit(R5_LOCKED, &sh->dev[i].flags);
-                       locked++;
+                       s.locked++;
                        set_bit(R5_Wantwrite, &sh->dev[i].flags);
                }
                clear_bit(STRIPE_EXPANDING, &sh->state);
-       } else if (expanded) {
+       } else if (s.expanded) {
                clear_bit(STRIPE_EXPAND_READY, &sh->state);
                atomic_dec(&conf->reshape_stripes);
                wake_up(&conf->wait_for_overlap);
                md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
        }
 
-       if (expanding && locked == 0) {
-               /* We have read all the blocks in this stripe and now we need to
-                * copy some of them into a target stripe for expand.
-                */
-               clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-               for (i = 0; i < sh->disks ; i++)
-                       if (i != pd_idx && i != qd_idx) {
-                               int dd_idx2, pd_idx2, j;
-                               struct stripe_head *sh2;
-
-                               sector_t bn = compute_blocknr(sh, i);
-                               sector_t s = raid5_compute_sector(
-                                       bn, conf->raid_disks,
-                                       conf->raid_disks - conf->max_degraded,
-                                       &dd_idx2, &pd_idx2, conf);
-                               sh2 = get_active_stripe(conf, s,
-                                                       conf->raid_disks,
-                                                      pd_idx2, 1);
-                               if (sh2 == NULL)
-                                       /* so for only the early blocks of
-                                        * this stripe have been requests.
-                                        * When later blocks get requests, we
-                                        * will try again
-                                        */
-                                       continue;
-                               if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
-                                   test_bit(R5_Expanded,
-                                            &sh2->dev[dd_idx2].flags)) {
-                                       /* must have already done this block */
-                                       release_stripe(sh2);
-                                       continue;
-                               }
-                               memcpy(page_address(sh2->dev[dd_idx2].page),
-                                      page_address(sh->dev[i].page),
-                                      STRIPE_SIZE);
-                               set_bit(R5_Expanded, &sh2->dev[dd_idx2].flags);
-                               set_bit(R5_UPTODATE, &sh2->dev[dd_idx2].flags);
-                               for (j = 0 ; j < conf->raid_disks ; j++)
-                                       if (j != sh2->pd_idx &&
-                                           j != raid6_next_disk(sh2->pd_idx,
-                                                          sh2->disks) &&
-                                           !test_bit(R5_Expanded,
-                                                     &sh2->dev[j].flags))
-                                               break;
-                               if (j == conf->raid_disks) {
-                                       set_bit(STRIPE_EXPAND_READY,
-                                               &sh2->state);
-                                       set_bit(STRIPE_HANDLE, &sh2->state);
-                               }
-                               release_stripe(sh2);
-                       }
-       }
+       if (s.expanding && s.locked == 0)
+               handle_stripe_expansion(conf, sh, &r6s);
 
        spin_unlock(&sh->lock);
 
-       while ((bi=return_bi)) {
-               int bytes = bi->bi_size;
+       return_io(return_bi);
 
-               return_bi = bi->bi_next;
-               bi->bi_next = NULL;
-               bi->bi_size = 0;
-               bi->bi_end_io(bi, bytes,
-                             test_bit(BIO_UPTODATE, &bi->bi_flags)
-                               ? 0 : -EIO);
-       }
        for (i=disks; i-- ;) {
                int rw;
                struct bio *bi;
@@ -2470,11 +3101,11 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                rcu_read_unlock();
 
                if (rdev) {
-                       if (syncing || expanding || expanded)
+                       if (s.syncing || s.expanding || s.expanded)
                                md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 
                        bi->bi_bdev = rdev->bdev;
-                       PRINTK("for %llu schedule op %ld on disc %d\n",
+                       pr_debug("for %llu schedule op %ld on disc %d\n",
                                (unsigned long long)sh->sector, bi->bi_rw, i);
                        atomic_inc(&sh->count);
                        bi->bi_sector = sh->sector + rdev->data_offset;
@@ -2494,7 +3125,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                } else {
                        if (rw == WRITE)
                                set_bit(STRIPE_DEGRADED, &sh->state);
-                       PRINTK("skip op %ld on disc %d for sector %llu\n",
+                       pr_debug("skip op %ld on disc %d for sector %llu\n",
                                bi->bi_rw, i, (unsigned long long)sh->sector);
                        clear_bit(R5_LOCKED, &sh->dev[i].flags);
                        set_bit(STRIPE_HANDLE, &sh->state);
@@ -2738,7 +3369,7 @@ static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error)
        }
 
 
-       PRINTK("raid5_align_endio : io error...handing IO for a retry\n");
+       pr_debug("raid5_align_endio : io error...handing IO for a retry\n");
 
        add_bio_to_retry(raid_bi, conf);
        return 0;
@@ -2776,7 +3407,7 @@ static int chunk_aligned_read(request_queue_t *q, struct bio * raid_bio)
        mdk_rdev_t *rdev;
 
        if (!in_chunk_boundary(mddev, raid_bio)) {
-               PRINTK("chunk_aligned_read : non aligned\n");
+               pr_debug("chunk_aligned_read : non aligned\n");
                return 0;
        }
        /*
@@ -2900,7 +3531,7 @@ static int make_request(request_queue_t *q, struct bio * bi)
 
                new_sector = raid5_compute_sector(logical_sector, disks, data_disks,
                                                  &dd_idx, &pd_idx, conf);
-               PRINTK("raid5: make_request, sector %llu logical %llu\n",
+               pr_debug("raid5: make_request, sector %llu logical %llu\n",
                        (unsigned long long)new_sector, 
                        (unsigned long long)logical_sector);
 
@@ -3273,7 +3904,7 @@ static void raid5d (mddev_t *mddev)
        raid5_conf_t *conf = mddev_to_conf(mddev);
        int handled;
 
-       PRINTK("+++ raid5d active\n");
+       pr_debug("+++ raid5d active\n");
 
        md_check_recovery(mddev);
 
@@ -3308,8 +3939,10 @@ static void raid5d (mddev_t *mddev)
                        handled++;
                }
 
-               if (list_empty(&conf->handle_list))
+               if (list_empty(&conf->handle_list)) {
+                       async_tx_issue_pending_all();
                        break;
+               }
 
                first = conf->handle_list.next;
                sh = list_entry(first, struct stripe_head, lru);
@@ -3325,13 +3958,13 @@ static void raid5d (mddev_t *mddev)
 
                spin_lock_irq(&conf->device_lock);
        }
-       PRINTK("%d stripes handled\n", handled);
+       pr_debug("%d stripes handled\n", handled);
 
        spin_unlock_irq(&conf->device_lock);
 
        unplug_slaves(mddev);
 
-       PRINTK("--- raid5d inactive\n");
+       pr_debug("--- raid5d inactive\n");
 }
 
 static ssize_t
@@ -3507,7 +4140,7 @@ static int run(mddev_t *mddev)
        atomic_set(&conf->preread_active_stripes, 0);
        atomic_set(&conf->active_aligned_reads, 0);
 
-       PRINTK("raid5: run(%s) called.\n", mdname(mddev));
+       pr_debug("raid5: run(%s) called.\n", mdname(mddev));
 
        ITERATE_RDEV(mddev,rdev,tmp) {
                raid_disk = rdev->raid_disk;
@@ -3690,7 +4323,7 @@ static int stop(mddev_t *mddev)
        return 0;
 }
 
-#if RAID5_DEBUG
+#ifdef DEBUG
 static void print_sh (struct seq_file *seq, struct stripe_head *sh)
 {
        int i;
@@ -3737,7 +4370,7 @@ static void status (struct seq_file *seq, mddev_t *mddev)
                               conf->disks[i].rdev &&
                               test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_");
        seq_printf (seq, "]");
-#if RAID5_DEBUG
+#ifdef DEBUG
        seq_printf (seq, "\n");
        printall(seq, conf);
 #endif
index fdf5d6e46eac1f5250d231c14a1fec1398462680..5e6f17df204b458e0c3b634d40498e79a6ece678 100644 (file)
@@ -94,7 +94,6 @@ struct gemtek_pci_card {
 
        u32 iobase;
        u32 length;
-       u8  chiprev;
        u16 model;
 
        u32 current_frequency;
@@ -415,7 +414,6 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
                goto err_pci;
        }
 
-       pci_read_config_byte( pci_dev, PCI_REVISION_ID, &card->chiprev );
        pci_read_config_word( pci_dev, PCI_SUBSYSTEM_ID, &card->model );
 
        pci_set_drvdata( pci_dev, card );
@@ -436,7 +434,7 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
        gemtek_pci_mute( card );
 
        printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
-               card->chiprev, card->iobase, card->iobase + card->length - 1 );
+               pci_dev->revision, card->iobase, card->iobase + card->length - 1 );
 
        return 0;
 
index 664aba8b4d85231895954ac48df4447212796d48..7533fc2033195b97e2648a82225514e7663007b1 100644 (file)
@@ -1809,7 +1809,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
 {
        int ret = -EBUSY;
        unsigned long mchip_adr;
-       u8 revision;
 
        if (meye.mchip_dev != NULL) {
                printk(KERN_ERR "meye: only one device allowed!\n");
@@ -1885,7 +1884,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
                goto outreqirq;
        }
 
-       pci_read_config_byte(meye.mchip_dev, PCI_REVISION_ID, &revision);
        pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8);
        pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64);
 
@@ -1939,7 +1937,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n",
               MEYE_DRIVER_VERSION);
        printk(KERN_INFO "meye: mchip KL5A72002 rev. %d, base %lx, irq %d\n",
-              revision, mchip_adr, meye.mchip_irq);
+              meye.mchip_dev->revision, mchip_adr, meye.mchip_irq);
 
        return 0;
 
index 4f9060a2a2f2fce960486d07132fa889179510aa..7798f590e5aab8c840b3f839d249926e67308343 100644 (file)
@@ -737,8 +737,7 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
        struct device_attribute dev_attr_##_name = {                    \
                .attr = {                                               \
                        .name = __stringify(_name),                     \
-                       .mode = 0,                                      \
-                       .owner = THIS_MODULE },                         \
+                       .mode = 0 },                                    \
                .show   = NULL,                                         \
                .store  = NULL,                                         \
        }
index 41e901f53e7c819699b909f2a3afcf7a3587e6b4..932a415197b3f636b5122f83c8472f4566fb1a75 100644 (file)
@@ -23,6 +23,8 @@
  * msi-laptop.c - MSI S270 laptop support. This laptop is sold under
  * various brands, including "Cytron/TCM/Medion/Tchibo MD96100".
  *
+ * Driver also supports S271, S420 models.
+ *
  * This driver exports a few files in /sys/devices/platform/msi-laptop-pf/:
  *
  *   lcd_level - Screen brightness: contains a single integer in the
@@ -281,25 +283,56 @@ static struct platform_device *msipf_device;
 
 /* Initialization */
 
+static int dmi_check_cb(struct dmi_system_id *id)
+{
+        printk("msi-laptop: Identified laptop model '%s'.\n", id->ident);
+        return 0;
+}
+
 static struct dmi_system_id __initdata msi_dmi_table[] = {
        {
                .ident = "MSI S270",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"),
-               }
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
+                       DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
+               },
+               .callback = dmi_check_cb
+       },
+       {
+               .ident = "MSI S271",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MS-1058"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "0581"),
+                       DMI_MATCH(DMI_BOARD_NAME, "MS-1058")
+               },
+               .callback = dmi_check_cb
+       },
+       {
+               .ident = "MSI S420",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MS-1412"),
+                       DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
+                       DMI_MATCH(DMI_BOARD_NAME, "MS-1412")
+               },
+               .callback = dmi_check_cb
        },
        {
                .ident = "Medion MD96100",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"),
-               }
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
+                       DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
+               },
+               .callback = dmi_check_cb
        },
        { }
 };
 
-
 static int __init msi_init(void)
 {
        int ret;
@@ -394,3 +427,8 @@ MODULE_AUTHOR("Lennart Poettering");
 MODULE_DESCRIPTION("MSI Laptop Support");
 MODULE_VERSION(MSI_DRIVER_VERSION);
 MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
+MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*");
+MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
+MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
index 1b163220df2bad67727bf242ab982333dd6b5e54..df17c281278a68d272a21756b1be5eb1f1d9c82f 100644 (file)
@@ -1,25 +1,3 @@
-#undef MMC_STRPCL
-#undef MMC_STAT
-#undef MMC_CLKRT
-#undef MMC_SPI
-#undef MMC_CMDAT
-#undef MMC_RESTO
-#undef MMC_RDTO
-#undef MMC_BLKLEN
-#undef MMC_NOB
-#undef MMC_PRTBUF
-#undef MMC_I_MASK
-#undef END_CMD_RES
-#undef PRG_DONE
-#undef DATA_TRAN_DONE
-#undef MMC_I_REG
-#undef MMC_CMD
-#undef MMC_ARGH
-#undef MMC_ARGL
-#undef MMC_RES
-#undef MMC_RXFIFO
-#undef MMC_TXFIFO
-
 #define MMC_STRPCL     0x0000
 #define STOP_CLOCK             (1 << 0)
 #define START_CLOCK            (2 << 0)
index 58bbc3e6d0de1af6960bd727adfaed7b713b2edc..807e6992e6142ef9399466f53ab038b89807d2cc 100644 (file)
@@ -1799,7 +1799,6 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        void __iomem *regs;
        resource_size_t pciaddr;
        unsigned int addr_len, i, pci_using_dac;
-       u8 pci_rev;
 
 #ifndef MODULE
        static int version_printed;
@@ -1807,13 +1806,11 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                printk("%s", version);
 #endif
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
        if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
-           pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev < 0x20) {
+           pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision < 0x20) {
                dev_err(&pdev->dev,
                           "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
-                          pdev->vendor, pdev->device, pci_rev);
+                          pdev->vendor, pdev->device, pdev->revision);
                dev_err(&pdev->dev, "Try the \"8139too\" driver instead.\n");
                return -ENODEV;
        }
index 21a6ccbf92e0de98f6effc192ba47f4aedae8786..327eaa7b4999183dee5ad600dc56b29efbbed787 100644 (file)
@@ -931,7 +931,6 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
        int i, addr_len, option;
        void __iomem *ioaddr;
        static int board_idx = -1;
-       u8 pci_rev;
 
        assert (pdev != NULL);
        assert (ent != NULL);
@@ -949,13 +948,11 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
        }
 #endif
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
        if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
-           pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) {
+           pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) {
                dev_info(&pdev->dev,
                           "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n",
-                          pdev->vendor, pdev->device, pci_rev);
+                          pdev->vendor, pdev->device, pdev->revision);
                dev_info(&pdev->dev,
                           "Use the \"8139cp\" driver for improved performance and stability.\n");
        }
index d4e39ff1545b5a698de24fa6f053aa8a28508d2d..d17d64eb7065e251e7b6f09f6060a9671b271e03 100644 (file)
@@ -82,6 +82,16 @@ config BONDING
          To compile this driver as a module, choose M here: the module
          will be called bonding.
 
+config MACVLAN
+       tristate "MAC-VLAN support (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       ---help---
+         This allows one to create virtual interfaces that map packets to
+         or from specific MAC addresses to a particular interface.
+
+         To compile this driver as a module, choose M here: the module
+         will be called macvlan.
+
 config EQUALIZER
        tristate "EQL (serial line load balancing) support"
        ---help---
@@ -885,7 +895,7 @@ config NET_NETX
 
 config DM9000
        tristate "DM9000 support"
-       depends on ARM || MIPS
+       depends on ARM || BLACKFIN || MIPS
        select CRC32
        select MII
        ---help---
index a2241e6e145765a896d90eb91cdbe8b9b54b53f0..c26b8674213cf33ac6c15fbd7a489b08ef44f550 100644 (file)
@@ -128,6 +128,7 @@ obj-$(CONFIG_SLHC) += slhc.o
 
 obj-$(CONFIG_DUMMY) += dummy.o
 obj-$(CONFIG_IFB) += ifb.o
+obj-$(CONFIG_MACVLAN) += macvlan.o
 obj-$(CONFIG_DE600) += de600.o
 obj-$(CONFIG_DE620) += de620.o
 obj-$(CONFIG_LANCE) += lance.o
index b1c6034e68fa320ddd48fabec94374d403e09ae5..df4c1a0071aa37a141d3018e80198c1d13e5880e 100644 (file)
@@ -210,7 +210,6 @@ struct atl1_hw {
        u16 phy_spd_default;
 
        u16 dev_rev;
-       u8 revision_id;
 
        /* spi flash */
        u8 flash_vendor;
index 3bb40dd4a410c9668309131eeb6d8e0c72eb1a54..501919eb7f5eab6242f28c682448f6f348839ecd 100644 (file)
@@ -118,10 +118,6 @@ static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
 {
        struct atl1_hw *hw = &adapter->hw;
        struct net_device *netdev = adapter->netdev;
-       struct pci_dev *pdev = adapter->pdev;
-
-       /* PCI config space info */
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
 
        hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
        hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
index d681903c592db0201adec04566b8407e087253a5..4e5e1cb2adc1d7019275e84349b00f73dfd82215 100644 (file)
@@ -40,6 +40,7 @@
 #define BCM_VLAN 1
 #endif
 #include <net/ip.h>
+#include <net/tcp.h>
 #include <net/checksum.h>
 #include <linux/workqueue.h>
 #include <linux/crc32.h>
@@ -6736,10 +6737,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD,
                                                  PCI_DEVICE_ID_AMD_8132_BRIDGE,
                                                  amd_8132))) {
-                       u8 rev;
 
-                       pci_read_config_byte(amd_8132, PCI_REVISION_ID, &rev);
-                       if (rev >= 0x10 && rev <= 0x13) {
+                       if (amd_8132->revision >= 0x10 &&
+                           amd_8132->revision <= 0x13) {
                                disable_msi = 1;
                                pci_dev_put(amd_8132);
                                break;
index 59b9943b077d4225c236a1a702fc5d9fbaa82f4b..f6e4030c73d118c043ca7daebfdc051ef78320f3 100644 (file)
@@ -3422,21 +3422,19 @@ done:
 static void cas_check_pci_invariants(struct cas *cp)
 {
        struct pci_dev *pdev = cp->pdev;
-       u8 rev;
 
        cp->cas_flags = 0;
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
        if ((pdev->vendor == PCI_VENDOR_ID_SUN) &&
            (pdev->device == PCI_DEVICE_ID_SUN_CASSINI)) {
-               if (rev >= CAS_ID_REVPLUS)
+               if (pdev->revision >= CAS_ID_REVPLUS)
                        cp->cas_flags |= CAS_FLAG_REG_PLUS;
-               if (rev < CAS_ID_REVPLUS02u)
+               if (pdev->revision < CAS_ID_REVPLUS02u)
                        cp->cas_flags |= CAS_FLAG_TARGET_ABORT;
 
                /* Original Cassini supports HW CSUM, but it's not
                 * enabled by default as it can trigger TX hangs.
                 */
-               if (rev < CAS_ID_REV2)
+               if (pdev->revision < CAS_ID_REV2)
                        cp->cas_flags |= CAS_FLAG_NO_HW_CSUM;
        } else {
                /* Only sun has original cassini chips.  */
@@ -4919,13 +4917,13 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
        pci_cmd &= ~PCI_COMMAND_SERR;
        pci_cmd |= PCI_COMMAND_PARITY;
        pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
-       if (pci_set_mwi(pdev))
+       if (pci_try_set_mwi(pdev))
                printk(KERN_WARNING PFX "Could not enable MWI for %s\n",
                       pci_name(pdev));
 
        /*
         * On some architectures, the default cache line size set
-        * by pci_set_mwi reduces perforamnce.  We have to increase
+        * by pci_try_set_mwi reduces perforamnce.  We have to increase
         * it for this case.  To start, we'll print some configuration
         * data.
         */
index 8eddd23a3a51c077cfd922870acc179d97e06c6a..eb508bf8022a0595bd228b2ede3e94040e39f782 100644 (file)
@@ -39,6 +39,6 @@
 
 /* Firmware version */
 #define FW_VERSION_MAJOR 4
-#define FW_VERSION_MINOR 1
+#define FW_VERSION_MINOR 3
 #define FW_VERSION_MICRO 0
 #endif                         /* __CHELSIO_VERSION_H */
index a4ace071f1cb5f1794b13d8b49b150d9ca11dbc2..04e3710c908269e3510a9492296ee041e75e717b 100644 (file)
@@ -250,7 +250,6 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
                        np->an_enable = 1;
                mii_set_media (dev);
        }
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id);
 
        err = register_netdev (dev);
        if (err)
@@ -879,7 +878,7 @@ receive_packet (struct net_device *dev)
                        skb->protocol = eth_type_trans (skb, dev);
 #if 0
                        /* Checksum done by hw, but csum value unavailable. */
-                       if (np->pci_rev_id >= 0x0c &&
+                       if (np->pdev->pci_rev_id >= 0x0c &&
                                !(frame_status & (TCPError | UDPError | IPError))) {
                                skb->ip_summed = CHECKSUM_UNNECESSARY;
                        }
index 814c449c359fac1f4255b59ccd9977b8458fcb72..e443065a452e690600b647250cedb2ababf1e8ab 100644 (file)
@@ -668,7 +668,6 @@ struct netdev_private {
        unsigned int rx_flow:1;         /* Rx flow control enable */
        unsigned int phy_media:1;       /* 1: fiber, 0: copper */
        unsigned int link_status:1;     /* Current link status */
-       unsigned char pci_rev_id;       /* PCI revision ID */
        struct netdev_desc *last_tx;    /* Last Tx descriptor used. */
        unsigned long cur_rx, old_rx;   /* Producer/consumer ring indices */
        unsigned long cur_tx, old_tx;
index 264fa0e2e0750401ff200a063f46e68a2f45378c..c3de81bf090a3f92062c236f560cee7f63fd1d69 100644 (file)
 #define PRINTK(args...)   printk(KERN_DEBUG args)
 #endif
 
+#ifdef CONFIG_BLACKFIN
+#define readsb insb
+#define readsw insw
+#define readsl insl
+#define writesb        outsb
+#define writesw        outsw
+#define writesl        outsl
+#define DM9000_IRQ_FLAGS       (IRQF_SHARED | IRQF_TRIGGER_HIGH)
+#else
+#define DM9000_IRQ_FLAGS       IRQF_SHARED
+#endif
+
 /*
  * Transmit timeout, default 5 seconds.
  */
@@ -431,6 +443,9 @@ dm9000_probe(struct platform_device *pdev)
                db->io_addr = (void __iomem *)base;
                db->io_data = (void __iomem *)(base + 4);
 
+               /* ensure at least we have a default set of IO routines */
+               dm9000_set_io(db, 2);
+
        } else {
                db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -614,7 +629,7 @@ dm9000_open(struct net_device *dev)
 
        PRINTK2("entering dm9000_open\n");
 
-       if (request_irq(dev->irq, &dm9000_interrupt, IRQF_SHARED, dev->name, dev))
+       if (request_irq(dev->irq, &dm9000_interrupt, DM9000_IRQ_FLAGS, dev->name, dev))
                return -EAGAIN;
 
        /* Initialize DM9000 board */
index 74ea6373c7cdbee27249807cce247a6085cd172c..6b6401e9304e6b2a298773019cb2c6d32f26a0f9 100644 (file)
@@ -583,7 +583,6 @@ struct nic {
        u32 rx_tco_frames;
        u32 rx_over_length_errors;
 
-       u8 rev_id;
        u16 leds;
        u16 eeprom_wc;
        u16 eeprom[256];
@@ -937,9 +936,8 @@ static void e100_get_defaults(struct nic *nic)
        struct param_range rfds = { .min = 16, .max = 256, .count = 256 };
        struct param_range cbs  = { .min = 64, .max = 256, .count = 128 };
 
-       pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id);
        /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
-       nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->rev_id;
+       nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision;
        if(nic->mac == mac_unknown)
                nic->mac = mac_82557_D100_A;
 
@@ -1279,7 +1277,7 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb
        if (nic->flags & ich)
                goto noloaducode;
 
-       /* Search for ucode match against h/w rev_id */
+       /* Search for ucode match against h/w revision */
        for (opts = ucode_opts; opts->mac; opts++) {
                int i;
                u32 *ucode = opts->ucode;
@@ -2238,7 +2236,7 @@ static void e100_get_regs(struct net_device *netdev,
        u32 *buff = p;
        int i;
 
-       regs->version = (1 << 24) | nic->rev_id;
+       regs->version = (1 << 24) | nic->pdev->revision;
        buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 |
                ioread8(&nic->csr->scb.cmd_lo) << 16 |
                ioread16(&nic->csr->scb.status);
index cf8af928a69cd4b9d157fb97cb6f6071dc421ba8..f48b659e0c2bd3dbdfbb6015ad22acdd5f876951 100644 (file)
@@ -1266,8 +1266,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
        hw->device_id = pdev->device;
        hw->subsystem_vendor_id = pdev->subsystem_vendor;
        hw->subsystem_id = pdev->subsystem_device;
-
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+       hw->revision_id = pdev->revision;
 
        pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
 
index 42ba1c012ee2c3ad0f20ec14588bd5751507e8f3..67046e8c21eb9a97051017cf2b90b8e733bc60c5 100644 (file)
@@ -5084,15 +5084,13 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        np->wolenabled = 0;
 
        if (id->driver_data & DEV_HAS_POWER_CNTRL) {
-               u8 revision_id;
-               pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id);
 
                /* take phy and nic out of low power mode */
                powerstate = readl(base + NvRegPowerState2);
                powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
                if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 ||
                     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) &&
-                   revision_id >= 0xA3)
+                   pci_dev->revision >= 0xA3)
                        powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
                writel(powerstate, base + NvRegPowerState2);
        }
index 6ec3d500f3341ac491519c60d27d2f2c1b936c45..d96eb72295488fe486136df191a3a0f8c8b6b96d 100644 (file)
@@ -1337,7 +1337,7 @@ const char * buf, size_t count)
 
 #define ATTR(_name, _mode)      \
         struct attribute veth_##_name##_attr = {               \
-        .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \
+        .name = __stringify(_name), .mode = _mode, \
         };
 
 static ATTR(active, 0644);
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
new file mode 100644 (file)
index 0000000..dc74d00
--- /dev/null
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * The code this is based on carried the following copyright notice:
+ * ---
+ * (C) Copyright 2001-2006
+ * Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com
+ * Re-worked by Ben Greear <greearb@candelatech.com>
+ * ---
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_arp.h>
+#include <linux/if_link.h>
+#include <linux/if_macvlan.h>
+#include <net/rtnetlink.h>
+
+#define MACVLAN_HASH_SIZE      (1 << BITS_PER_BYTE)
+
+struct macvlan_port {
+       struct net_device       *dev;
+       struct hlist_head       vlan_hash[MACVLAN_HASH_SIZE];
+       struct list_head        vlans;
+};
+
+struct macvlan_dev {
+       struct net_device       *dev;
+       struct list_head        list;
+       struct hlist_node       hlist;
+       struct macvlan_port     *port;
+       struct net_device       *lowerdev;
+};
+
+
+static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
+                                              const unsigned char *addr)
+{
+       struct macvlan_dev *vlan;
+       struct hlist_node *n;
+
+       hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[addr[5]], hlist) {
+               if (!compare_ether_addr(vlan->dev->dev_addr, addr))
+                       return vlan;
+       }
+       return NULL;
+}
+
+static void macvlan_broadcast(struct sk_buff *skb,
+                             const struct macvlan_port *port)
+{
+       const struct ethhdr *eth = eth_hdr(skb);
+       const struct macvlan_dev *vlan;
+       struct hlist_node *n;
+       struct net_device *dev;
+       struct sk_buff *nskb;
+       unsigned int i;
+
+       for (i = 0; i < MACVLAN_HASH_SIZE; i++) {
+               hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) {
+                       dev = vlan->dev;
+                       if (unlikely(!(dev->flags & IFF_UP)))
+                               continue;
+
+                       nskb = skb_clone(skb, GFP_ATOMIC);
+                       if (nskb == NULL) {
+                               dev->stats.rx_errors++;
+                               dev->stats.rx_dropped++;
+                               continue;
+                       }
+
+                       dev->stats.rx_bytes += skb->len + ETH_HLEN;
+                       dev->stats.rx_packets++;
+                       dev->stats.multicast++;
+                       dev->last_rx = jiffies;
+
+                       nskb->dev = dev;
+                       if (!compare_ether_addr(eth->h_dest, dev->broadcast))
+                               nskb->pkt_type = PACKET_BROADCAST;
+                       else
+                               nskb->pkt_type = PACKET_MULTICAST;
+
+                       netif_rx(nskb);
+               }
+       }
+}
+
+/* called under rcu_read_lock() from netif_receive_skb */
+static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
+{
+       const struct ethhdr *eth = eth_hdr(skb);
+       const struct macvlan_port *port;
+       const struct macvlan_dev *vlan;
+       struct net_device *dev;
+
+       port = rcu_dereference(skb->dev->macvlan_port);
+       if (port == NULL)
+               return skb;
+
+       if (is_multicast_ether_addr(eth->h_dest)) {
+               macvlan_broadcast(skb, port);
+               return skb;
+       }
+
+       vlan = macvlan_hash_lookup(port, eth->h_dest);
+       if (vlan == NULL)
+               return skb;
+
+       dev = vlan->dev;
+       if (unlikely(!(dev->flags & IFF_UP))) {
+               kfree_skb(skb);
+               return NULL;
+       }
+
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (skb == NULL) {
+               dev->stats.rx_errors++;
+               dev->stats.rx_dropped++;
+               return NULL;
+       }
+
+       dev->stats.rx_bytes += skb->len + ETH_HLEN;
+       dev->stats.rx_packets++;
+       dev->last_rx = jiffies;
+
+       skb->dev = dev;
+       skb->pkt_type = PACKET_HOST;
+
+       netif_rx(skb);
+       return NULL;
+}
+
+static int macvlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       const struct macvlan_dev *vlan = netdev_priv(dev);
+       unsigned int len = skb->len;
+       int ret;
+
+       skb->dev = vlan->lowerdev;
+       ret = dev_queue_xmit(skb);
+
+       if (likely(ret == NET_XMIT_SUCCESS)) {
+               dev->stats.tx_packets++;
+               dev->stats.tx_bytes += len;
+       } else {
+               dev->stats.tx_errors++;
+               dev->stats.tx_aborted_errors++;
+       }
+       return NETDEV_TX_OK;
+}
+
+static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
+                              unsigned short type, void *daddr, void *saddr,
+                              unsigned len)
+{
+       const struct macvlan_dev *vlan = netdev_priv(dev);
+       struct net_device *lowerdev = vlan->lowerdev;
+
+       return lowerdev->hard_header(skb, lowerdev, type, daddr,
+                                    saddr ? : dev->dev_addr, len);
+}
+
+static int macvlan_open(struct net_device *dev)
+{
+       struct macvlan_dev *vlan = netdev_priv(dev);
+       struct macvlan_port *port = vlan->port;
+       struct net_device *lowerdev = vlan->lowerdev;
+       int err;
+
+       err = dev_unicast_add(lowerdev, dev->dev_addr, ETH_ALEN);
+       if (err < 0)
+               return err;
+       if (dev->flags & IFF_ALLMULTI)
+               dev_set_allmulti(lowerdev, 1);
+
+       hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[dev->dev_addr[5]]);
+       return 0;
+}
+
+static int macvlan_stop(struct net_device *dev)
+{
+       struct macvlan_dev *vlan = netdev_priv(dev);
+       struct net_device *lowerdev = vlan->lowerdev;
+
+       dev_mc_unsync(lowerdev, dev);
+       if (dev->flags & IFF_ALLMULTI)
+               dev_set_allmulti(lowerdev, -1);
+
+       dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN);
+
+       hlist_del_rcu(&vlan->hlist);
+       synchronize_rcu();
+       return 0;
+}
+
+static void macvlan_change_rx_flags(struct net_device *dev, int change)
+{
+       struct macvlan_dev *vlan = netdev_priv(dev);
+       struct net_device *lowerdev = vlan->lowerdev;
+
+       if (change & IFF_ALLMULTI)
+               dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
+}
+
+static void macvlan_set_multicast_list(struct net_device *dev)
+{
+       struct macvlan_dev *vlan = netdev_priv(dev);
+
+       dev_mc_sync(vlan->lowerdev, dev);
+}
+
+static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
+{
+       struct macvlan_dev *vlan = netdev_priv(dev);
+
+       if (new_mtu < 68 || vlan->lowerdev->mtu < new_mtu)
+               return -EINVAL;
+       dev->mtu = new_mtu;
+       return 0;
+}
+
+/*
+ * macvlan network devices have devices nesting below it and are a special
+ * "super class" of normal network devices; split their locks off into a
+ * separate class since they always nest.
+ */
+static struct lock_class_key macvlan_netdev_xmit_lock_key;
+
+#define MACVLAN_FEATURES \
+       (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
+        NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \
+        NETIF_F_TSO_ECN | NETIF_F_TSO6)
+
+#define MACVLAN_STATE_MASK \
+       ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
+
+static int macvlan_init(struct net_device *dev)
+{
+       struct macvlan_dev *vlan = netdev_priv(dev);
+       const struct net_device *lowerdev = vlan->lowerdev;
+
+       dev->state              = (dev->state & ~MACVLAN_STATE_MASK) |
+                                 (lowerdev->state & MACVLAN_STATE_MASK);
+       dev->features           = lowerdev->features & MACVLAN_FEATURES;
+       dev->iflink             = lowerdev->ifindex;
+
+       lockdep_set_class(&dev->_xmit_lock, &macvlan_netdev_xmit_lock_key);
+       return 0;
+}
+
+static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
+                                       struct ethtool_drvinfo *drvinfo)
+{
+       snprintf(drvinfo->driver, 32, "macvlan");
+       snprintf(drvinfo->version, 32, "0.1");
+}
+
+static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev)
+{
+       const struct macvlan_dev *vlan = netdev_priv(dev);
+       struct net_device *lowerdev = vlan->lowerdev;
+
+       if (lowerdev->ethtool_ops->get_rx_csum == NULL)
+               return 0;
+       return lowerdev->ethtool_ops->get_rx_csum(lowerdev);
+}
+
+static const struct ethtool_ops macvlan_ethtool_ops = {
+       .get_link               = ethtool_op_get_link,
+       .get_rx_csum            = macvlan_ethtool_get_rx_csum,
+       .get_tx_csum            = ethtool_op_get_tx_csum,
+       .get_tso                = ethtool_op_get_tso,
+       .get_ufo                = ethtool_op_get_ufo,
+       .get_sg                 = ethtool_op_get_sg,
+       .get_drvinfo            = macvlan_ethtool_get_drvinfo,
+};
+
+static void macvlan_setup(struct net_device *dev)
+{
+       ether_setup(dev);
+
+       dev->init               = macvlan_init;
+       dev->open               = macvlan_open;
+       dev->stop               = macvlan_stop;
+       dev->change_mtu         = macvlan_change_mtu;
+       dev->change_rx_flags    = macvlan_change_rx_flags;
+       dev->set_multicast_list = macvlan_set_multicast_list;
+       dev->hard_header        = macvlan_hard_header;
+       dev->hard_start_xmit    = macvlan_hard_start_xmit;
+       dev->destructor         = free_netdev;
+       dev->ethtool_ops        = &macvlan_ethtool_ops;
+       dev->tx_queue_len       = 0;
+}
+
+static int macvlan_port_create(struct net_device *dev)
+{
+       struct macvlan_port *port;
+       unsigned int i;
+
+       if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK)
+               return -EINVAL;
+
+       port = kzalloc(sizeof(*port), GFP_KERNEL);
+       if (port == NULL)
+               return -ENOMEM;
+
+       port->dev = dev;
+       INIT_LIST_HEAD(&port->vlans);
+       for (i = 0; i < MACVLAN_HASH_SIZE; i++)
+               INIT_HLIST_HEAD(&port->vlan_hash[i]);
+       rcu_assign_pointer(dev->macvlan_port, port);
+       return 0;
+}
+
+static void macvlan_port_destroy(struct net_device *dev)
+{
+       struct macvlan_port *port = dev->macvlan_port;
+
+       rcu_assign_pointer(dev->macvlan_port, NULL);
+       synchronize_rcu();
+       kfree(port);
+}
+
+static void macvlan_transfer_operstate(struct net_device *dev)
+{
+       struct macvlan_dev *vlan = netdev_priv(dev);
+       const struct net_device *lowerdev = vlan->lowerdev;
+
+       if (lowerdev->operstate == IF_OPER_DORMANT)
+               netif_dormant_on(dev);
+       else
+               netif_dormant_off(dev);
+
+       if (netif_carrier_ok(lowerdev)) {
+               if (!netif_carrier_ok(dev))
+                       netif_carrier_on(dev);
+       } else {
+               if (netif_carrier_ok(lowerdev))
+                       netif_carrier_off(dev);
+       }
+}
+
+static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+       if (tb[IFLA_ADDRESS]) {
+               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+                       return -EINVAL;
+               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+                       return -EADDRNOTAVAIL;
+       }
+       return 0;
+}
+
+static int macvlan_newlink(struct net_device *dev,
+                          struct nlattr *tb[], struct nlattr *data[])
+{
+       struct macvlan_dev *vlan = netdev_priv(dev);
+       struct macvlan_port *port;
+       struct net_device *lowerdev;
+       int err;
+
+       if (!tb[IFLA_LINK])
+               return -EINVAL;
+
+       lowerdev = __dev_get_by_index(nla_get_u32(tb[IFLA_LINK]));
+       if (lowerdev == NULL)
+               return -ENODEV;
+
+       if (!tb[IFLA_MTU])
+               dev->mtu = lowerdev->mtu;
+       else if (dev->mtu > lowerdev->mtu)
+               return -EINVAL;
+
+       if (!tb[IFLA_ADDRESS])
+               random_ether_addr(dev->dev_addr);
+
+       if (lowerdev->macvlan_port == NULL) {
+               err = macvlan_port_create(lowerdev);
+               if (err < 0)
+                       return err;
+       }
+       port = lowerdev->macvlan_port;
+
+       vlan->lowerdev = lowerdev;
+       vlan->dev      = dev;
+       vlan->port     = port;
+
+       err = register_netdevice(dev);
+       if (err < 0)
+               return err;
+
+       list_add_tail(&vlan->list, &port->vlans);
+       macvlan_transfer_operstate(dev);
+       return 0;
+}
+
+static void macvlan_dellink(struct net_device *dev)
+{
+       struct macvlan_dev *vlan = netdev_priv(dev);
+       struct macvlan_port *port = vlan->port;
+
+       list_del(&vlan->list);
+       unregister_netdevice(dev);
+
+       if (list_empty(&port->vlans))
+               macvlan_port_destroy(dev);
+}
+
+static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
+       .kind           = "macvlan",
+       .priv_size      = sizeof(struct macvlan_dev),
+       .setup          = macvlan_setup,
+       .validate       = macvlan_validate,
+       .newlink        = macvlan_newlink,
+       .dellink        = macvlan_dellink,
+};
+
+static int macvlan_device_event(struct notifier_block *unused,
+                               unsigned long event, void *ptr)
+{
+       struct net_device *dev = ptr;
+       struct macvlan_dev *vlan, *next;
+       struct macvlan_port *port;
+
+       port = dev->macvlan_port;
+       if (port == NULL)
+               return NOTIFY_DONE;
+
+       switch (event) {
+       case NETDEV_CHANGE:
+               list_for_each_entry(vlan, &port->vlans, list)
+                       macvlan_transfer_operstate(vlan->dev);
+               break;
+       case NETDEV_FEAT_CHANGE:
+               list_for_each_entry(vlan, &port->vlans, list) {
+                       vlan->dev->features = dev->features & MACVLAN_FEATURES;
+                       netdev_features_change(vlan->dev);
+               }
+               break;
+       case NETDEV_UNREGISTER:
+               list_for_each_entry_safe(vlan, next, &port->vlans, list)
+                       macvlan_dellink(vlan->dev);
+               break;
+       }
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block macvlan_notifier_block __read_mostly = {
+       .notifier_call  = macvlan_device_event,
+};
+
+static int __init macvlan_init_module(void)
+{
+       int err;
+
+       register_netdevice_notifier(&macvlan_notifier_block);
+       macvlan_handle_frame_hook = macvlan_handle_frame;
+
+       err = rtnl_link_register(&macvlan_link_ops);
+       if (err < 0)
+               goto err1;
+       return 0;
+err1:
+       macvlan_handle_frame_hook = macvlan_handle_frame;
+       unregister_netdevice_notifier(&macvlan_notifier_block);
+       return err;
+}
+
+static void __exit macvlan_cleanup_module(void)
+{
+       rtnl_link_unregister(&macvlan_link_ops);
+       macvlan_handle_frame_hook = NULL;
+       unregister_netdevice_notifier(&macvlan_notifier_block);
+}
+
+module_init(macvlan_init_module);
+module_exit(macvlan_cleanup_module);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("Driver for MAC address based VLANs");
+MODULE_ALIAS_RTNL_LINK("macvlan");
index d2b065351e4511fda36c5e4bd101c15e2fd647b6..c45cbe43a0c483830891e109beb306d11dc51d2a 100644 (file)
@@ -138,6 +138,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 #define QUERY_DEV_CAP_ACK_DELAY_OFFSET         0x35
 #define QUERY_DEV_CAP_MTU_WIDTH_OFFSET         0x36
 #define QUERY_DEV_CAP_VL_PORT_OFFSET           0x37
+#define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET                0x38
 #define QUERY_DEV_CAP_MAX_GID_OFFSET           0x3b
 #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET      0x3c
 #define QUERY_DEV_CAP_MAX_PKEY_OFFSET          0x3f
@@ -220,6 +221,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
        dev_cap->local_ca_ack_delay = field & 0x1f;
        MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
        dev_cap->num_ports = field & 0xf;
+       MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET);
+       dev_cap->max_msg_sz = 1 << (field & 0x1f);
        MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
        dev_cap->stat_rate_support = stat_rate;
        MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
index 296254ac27c14b0a5fbfa0f3789e149e91336e80..7e1dd9e25cfbabb9fa995d51c2c1fbf149518de6 100644 (file)
@@ -60,6 +60,7 @@ struct mlx4_dev_cap {
        int max_rdma_global;
        int local_ca_ack_delay;
        int num_ports;
+       u32 max_msg_sz;
        int max_mtu[MLX4_MAX_PORTS + 1];
        int max_port_width[MLX4_MAX_PORTS + 1];
        int max_vl[MLX4_MAX_PORTS + 1];
index c3da2a2f543127c7b89a34af0b1279923b4a3496..a4f2e0475a719e249358a54f5cd2c892ad5c12e0 100644 (file)
@@ -154,6 +154,7 @@ static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev
        dev->caps.reserved_uars      = dev_cap->reserved_uars;
        dev->caps.reserved_pds       = dev_cap->reserved_pds;
        dev->caps.mtt_entry_sz       = MLX4_MTT_ENTRY_PER_SEG * dev_cap->mtt_entry_sz;
+       dev->caps.max_msg_sz         = dev_cap->max_msg_sz;
        dev->caps.page_size_cap      = ~(u32) (dev_cap->min_page_sz - 1);
        dev->caps.flags              = dev_cap->flags;
        dev->caps.stat_rate_support  = dev_cap->stat_rate_support;
index 3d3b6d24d8d3689a3116501c0baf100a8c182720..d9c91a71fc873b71ba85bd8b242df9e830eb3972 100644 (file)
@@ -37,6 +37,7 @@
 #ifndef MLX4_H
 #define MLX4_H
 
+#include <linux/mutex.h>
 #include <linux/radix-tree.h>
 
 #include <linux/mlx4/device.h>
index 492cfaaaa75cbf3b687214df37462f268118ce7e..19b48c71cf7f2e315eb31ba8a47af6b824c2d181 100644 (file)
@@ -277,3 +277,24 @@ void mlx4_cleanup_qp_table(struct mlx4_dev *dev)
        mlx4_CONF_SPECIAL_QP(dev, 0);
        mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap);
 }
+
+int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
+                 struct mlx4_qp_context *context)
+{
+       struct mlx4_cmd_mailbox *mailbox;
+       int err;
+
+       mailbox = mlx4_alloc_cmd_mailbox(dev);
+       if (IS_ERR(mailbox))
+               return PTR_ERR(mailbox);
+
+       err = mlx4_cmd_box(dev, 0, mailbox->dma, qp->qpn, 0,
+                          MLX4_CMD_QUERY_QP, MLX4_CMD_TIME_CLASS_A);
+       if (!err)
+               memcpy(context, mailbox->buf + 8, sizeof *context);
+
+       mlx4_free_cmd_mailbox(dev, mailbox);
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_qp_query);
+
index 2134f83aed8769fd9398e7365271e9e397e926ab..b061c86d6839aa3bd72aa0a7828f98c477b4bec9 100644 (file)
@@ -102,6 +102,13 @@ static int mlx4_ARM_SRQ(struct mlx4_dev *dev, int srq_num, int limit_watermark)
                        MLX4_CMD_TIME_CLASS_B);
 }
 
+static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+                         int srq_num)
+{
+       return mlx4_cmd_box(dev, 0, mailbox->dma, srq_num, 0, MLX4_CMD_QUERY_SRQ,
+                           MLX4_CMD_TIME_CLASS_A);
+}
+
 int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
                   u64 db_rec, struct mlx4_srq *srq)
 {
@@ -205,6 +212,29 @@ int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark
 }
 EXPORT_SYMBOL_GPL(mlx4_srq_arm);
 
+int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark)
+{
+       struct mlx4_cmd_mailbox *mailbox;
+       struct mlx4_srq_context *srq_context;
+       int err;
+
+       mailbox = mlx4_alloc_cmd_mailbox(dev);
+       if (IS_ERR(mailbox))
+               return PTR_ERR(mailbox);
+
+       srq_context = mailbox->buf;
+
+       err = mlx4_QUERY_SRQ(dev, mailbox, srq->srqn);
+       if (err)
+               goto err_out;
+       *limit_watermark = srq_context->limit_watermark;
+
+err_out:
+       mlx4_free_cmd_mailbox(dev, mailbox);
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_srq_query);
+
 int __devinit mlx4_init_srq_table(struct mlx4_dev *dev)
 {
        struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
index 56f8197b953b6ccce851a3aaee5a9a9449c540f4..b703ccfe040b41319e429d6780cf78cb72f9f3d5 100644 (file)
@@ -54,8 +54,6 @@ static char netxen_nic_driver_string[] = "NetXen Network Driver version "
 #define NETXEN_ADAPTER_UP_MAGIC 777
 #define NETXEN_NIC_PEG_TUNE 0
 
-u8 nx_p2_id = NX_P2_C0;
-
 #define DMA_32BIT_MASK 0x00000000ffffffffULL
 #define DMA_35BIT_MASK 0x00000007ffffffffULL
 
@@ -307,8 +305,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_out_disable_pdev;
 
        pci_set_master(pdev);
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id);
-       if (nx_p2_id == NX_P2_C1 &&
+       if (pdev->revision == NX_P2_C1 &&
            (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) &&
            (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) {
                pci_using_dac = 1;
@@ -552,7 +549,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
        adapter->ahw.pdev = pdev;
        adapter->proc_cmd_buf_counter = 0;
-       adapter->ahw.revision_id = nx_p2_id;
+       adapter->ahw.revision_id = pdev->revision;
 
        /* make sure Window == 1 */
        netxen_nic_pci_change_crbwindow(adapter, 1);
index fa29a403a247a8bfc2146651c273657bbf3a7e72..58bbfdd4f9016e29026fbe8527a46966f626619e 100644 (file)
@@ -1135,7 +1135,7 @@ static int init_nic(struct s2io_nic *nic)
         * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
         */
        if ((nic->device_type == XFRAME_I_DEVICE) &&
-               (get_xena_rev_id(nic->pdev) < 4))
+               (nic->pdev->revision < 4))
                writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable);
 
        val64 = readq(&bar0->tx_fifo_partition_0);
@@ -1873,7 +1873,7 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag)
        herc = (sp->device_type == XFRAME_II_DEVICE);
 
        if (flag == FALSE) {
-               if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
+               if ((!herc && (sp->pdev->revision >= 4)) || herc) {
                        if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE))
                                ret = 1;
                } else {
@@ -1881,7 +1881,7 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag)
                                ret = 1;
                }
        } else {
-               if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
+               if ((!herc && (sp->pdev->revision >= 4)) || herc) {
                        if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
                             ADAPTER_STATUS_RMAC_PCC_IDLE))
                                ret = 1;
@@ -7075,23 +7075,6 @@ static void s2io_link(struct s2io_nic * sp, int link)
        sp->start_time = jiffies;
 }
 
-/**
- *  get_xena_rev_id - to identify revision ID of xena.
- *  @pdev : PCI Dev structure
- *  Description:
- *  Function to identify the Revision ID of xena.
- *  Return value:
- *  returns the revision ID of the device.
- */
-
-static int get_xena_rev_id(struct pci_dev *pdev)
-{
-       u8 id = 0;
-       int ret;
-       ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id);
-       return id;
-}
-
 /**
  *  s2io_init_pci -Initialization of PCI and PCI-X configuration registers .
  *  @sp : private member of the device structure, which is a pointer to the
@@ -7550,7 +7533,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        s2io_vpd_read(sp);
        DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2007 Neterion Inc.\n");
        DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n",dev->name,
-                 sp->product_name, get_xena_rev_id(sp->pdev));
+                 sp->product_name, pdev->revision);
        DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name,
                  s2io_driver_version);
        DBG_PRINT(ERR_DBG, "%s: MAC ADDR: "
index 58592780f5198b77cfb6517ada8b0db02450a7ce..3887fe63a908146bc2fdff545a73ed2eebab098e 100644 (file)
@@ -1033,7 +1033,6 @@ static void s2io_set_link(struct work_struct *work);
 static int s2io_set_swapper(struct s2io_nic * sp);
 static void s2io_card_down(struct s2io_nic *nic);
 static int s2io_card_up(struct s2io_nic *nic);
-static int get_xena_rev_id(struct pci_dev *pdev);
 static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit,
                                        int bit_state);
 static int s2io_add_isr(struct s2io_nic * sp);
index f2e1019672042da445cf3d5269d56ddf0deded20..8b6478663a56b029c9322cb6cb239f00328cdc7f 100644 (file)
@@ -740,7 +740,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        pci_set_master(pdev);
 
        /* enable MWI -- it vastly improves Rx performance on sparc64 */
-       pci_set_mwi(pdev);
+       pci_try_set_mwi(pdev);
 
 #ifdef ZEROCOPY
        /* Starfire can do TCP/UDP checksumming */
index c8ba534c17bf969972a088fdb7e838ad59c15738..af0c9831074c62c4c9d14d4fad624fcd81bd0391 100644 (file)
@@ -397,7 +397,6 @@ struct netdev_private {
        unsigned char phys[MII_CNT];            /* MII device addresses, only first one used. */
        struct pci_dev *pci_dev;
        void __iomem *base;
-       unsigned char pci_rev_id;
 };
 
 /* The station address location in the EEPROM. */
@@ -544,8 +543,6 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
        dev->change_mtu = &change_mtu;
        pci_set_drvdata(pdev, dev);
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id);
-
        i = register_netdev(dev);
        if (i)
                goto err_out_unmap_rx;
@@ -828,7 +825,7 @@ static int netdev_open(struct net_device *dev)
        iowrite8(100, ioaddr + RxDMAPollPeriod);
        iowrite8(127, ioaddr + TxDMAPollPeriod);
        /* Fix DFE-580TX packet drop issue */
-       if (np->pci_rev_id >= 0x14)
+       if (np->pci_dev->revision >= 0x14)
                iowrite8(0x01, ioaddr + DebugCtrl1);
        netif_start_queue(dev);
 
@@ -1194,7 +1191,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
                        hw_frame_id = ioread8(ioaddr + TxFrameId);
                }
 
-               if (np->pci_rev_id >= 0x14) {
+               if (np->pci_dev->revision >= 0x14) {
                        spin_lock(&np->lock);
                        for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
                                int entry = np->dirty_tx % TX_RING_SIZE;
index 15146a119230e6b9d48dd00c74654aeff4d11a47..8b35f13318ea4b9e02b87644ed955a897985219d 100644 (file)
@@ -3095,12 +3095,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
 
 #ifdef CONFIG_SPARC
        hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff);
-       if (hp->hm_revision == 0xff) {
-               unsigned char prev;
-
-               pci_read_config_byte(pdev, PCI_REVISION_ID, &prev);
-               hp->hm_revision = 0xc0 | (prev & 0x0f);
-       }
+       if (hp->hm_revision == 0xff)
+               hp->hm_revision = 0xc0 | (pdev->revision & 0x0f);
 #else
        /* works with this on non-sparc hosts */
        hp->hm_revision = 0x20;
index 3245f16baabce51e87edde3918e6606a3b577a32..32e4037dcb50a3ec73961e2021cac643b9f21034 100644 (file)
@@ -10551,11 +10551,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                                continue;
                        }
                        if (pci_id->rev != PCI_ANY_ID) {
-                               u8 rev;
-
-                               pci_read_config_byte(bridge, PCI_REVISION_ID,
-                                                    &rev);
-                               if (rev > pci_id->rev)
+                               if (bridge->revision > pci_id->rev)
                                        continue;
                        }
                        if (bridge->subordinate &&
index 106dc1ef0acb95c37e3c8d21f2721858239c8585..74eb12107e6874c0ba101993a48f1f44094dc34a 100644 (file)
@@ -533,7 +533,6 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
 
        struct net_device  *dev;
        TLanPrivateInfo    *priv;
-       u8                 pci_rev;
        u16                device_id;
        int                reg, rc = -ENODEV;
 
@@ -577,8 +576,6 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
                        goto err_out_free_dev;
                }
 
-               pci_read_config_byte ( pdev, PCI_REVISION_ID, &pci_rev);
-
                for ( reg= 0; reg <= 5; reg ++ ) {
                        if (pci_resource_flags(pdev, reg) & IORESOURCE_IO) {
                                pci_io_base = pci_resource_start(pdev, reg);
@@ -595,7 +592,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
 
                dev->base_addr = pci_io_base;
                dev->irq = pdev->irq;
-               priv->adapterRev = pci_rev;
+               priv->adapterRev = pdev->revision;
                pci_set_master(pdev);
                pci_set_drvdata(pdev, dev);
 
index 42fca26afc500fef9c40fc1b109df1b9b91d3246..09902891a6e6549541a3a0d1e904cfe9df51e53f 100644 (file)
@@ -2134,7 +2134,7 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
     u_short vendor, status;
     u_int irq = 0, device;
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
-    int i, j, cfrv;
+    int i, j;
     struct de4x5_private *lp = netdev_priv(dev);
     struct list_head *walk;
 
@@ -2150,7 +2150,6 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
 
        /* Get the chip configuration revision register */
        pb = this_dev->bus->number;
-       pci_read_config_dword(this_dev, PCI_REVISION_ID, &cfrv);
 
        /* Set the device number information */
        lp->device = PCI_SLOT(this_dev->devfn);
@@ -2158,7 +2157,8 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
 
        /* Set the chipset information */
        if (is_DC2114x) {
-           device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
+           device = ((this_dev->revision & CFRV_RN) < DC2114x_BRK
+                     ? DC21142 : DC21143);
        }
        lp->chipset = device;
 
@@ -2254,7 +2254,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
        }
 
        /* Get the chip configuration revision register */
-       pci_read_config_dword(pdev, PCI_REVISION_ID, &lp->cfrv);
+       lp->cfrv = pdev->revision;
 
        /* Set the device number information */
        lp->device = dev_num;
index 4ed67ff0e81ef9b8329ba922e9015e0f582645e3..dab74feb44bcf125937d66d674a87c806592f64b 100644 (file)
        udelay(5);
 
 #define __CHK_IO_SIZE(pci_id, dev_rev) \
- (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? \
+ (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x30) ) ? \
        DM9102A_IO_SIZE: DM9102_IO_SIZE)
 
-#define CHK_IO_SIZE(pci_dev, dev_rev) \
-       (__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev))
+#define CHK_IO_SIZE(pci_dev) \
+       (__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, \
+       (pci_dev)->revision))
 
 /* Sten Check */
 #define DEVICE net_device
@@ -205,7 +206,7 @@ struct rx_desc {
 
 struct dmfe_board_info {
        u32 chip_id;                    /* Chip vendor/Device ID */
-       u32 chip_revision;              /* Chip revision */
+       u8 chip_revision;               /* Chip revision */
        struct DEVICE *next_dev;        /* next device */
        struct pci_dev *pdev;           /* PCI device */
        spinlock_t lock;
@@ -359,7 +360,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
 {
        struct dmfe_board_info *db;     /* board information structure */
        struct net_device *dev;
-       u32 dev_rev, pci_pmr;
+       u32 pci_pmr;
        int i, err;
 
        DMFE_DBUG(0, "dmfe_init_one()", 0);
@@ -392,10 +393,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
                goto err_out_disable;
        }
 
-       /* Read Chip revision */
-       pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev);
-
-       if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev, dev_rev)) ) {
+       if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev)) ) {
                printk(KERN_ERR DRV_NAME ": Allocated I/O size too small\n");
                err = -ENODEV;
                goto err_out_disable;
@@ -433,7 +431,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
 
        db->chip_id = ent->driver_data;
        db->ioaddr = pci_resource_start(pdev, 0);
-       db->chip_revision = dev_rev;
+       db->chip_revision = pdev->revision;
        db->wol_mode = 0;
 
        db->pdev = pdev;
@@ -455,7 +453,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
 
        pci_read_config_dword(pdev, 0x50, &pci_pmr);
        pci_pmr &= 0x70000;
-       if ( (pci_pmr == 0x10000) && (dev_rev == 0x02000031) )
+       if ( (pci_pmr == 0x10000) && (db->chip_revision == 0x31) )
                db->chip_type = 1;      /* DM9102A E3 */
        else
                db->chip_type = 0;
@@ -553,7 +551,7 @@ static int dmfe_open(struct DEVICE *dev)
 
        /* CR6 operation mode decision */
        if ( !chkmode || (db->chip_id == PCI_DM9132_ID) ||
-               (db->chip_revision >= 0x02000030) ) {
+               (db->chip_revision >= 0x30) ) {
                db->cr6_data |= DMFE_TXTH_256;
                db->cr0_data = CR0_DEFAULT;
                db->dm910x_chk_mode=4;          /* Enter the normal mode */
@@ -1199,9 +1197,9 @@ static void dmfe_timer(unsigned long data)
                tmp_cr12 = inb(db->ioaddr + DCR12);     /* DM9102/DM9102A */
 
        if ( ((db->chip_id == PCI_DM9102_ID) &&
-               (db->chip_revision == 0x02000030)) ||
+               (db->chip_revision == 0x30)) ||
                ((db->chip_id == PCI_DM9132_ID) &&
-               (db->chip_revision == 0x02000010)) ) {
+               (db->chip_revision == 0x10)) ) {
                /* DM9102A Chip */
                if (tmp_cr12 & 2)
                        link_ok = 0;
index 041af63f2811c4cb35ddf7f63a6dcea2c8b33412..7dcd138b0fed3be05888640047f400882c894e1b 100644 (file)
@@ -1155,7 +1155,7 @@ static void __devinit tulip_mwi_config (struct pci_dev *pdev,
        /* set or disable MWI in the standard PCI command bit.
         * Check for the case where  mwi is desired but not available
         */
-       if (csr0 & MWI) pci_set_mwi(pdev);
+       if (csr0 & MWI) pci_try_set_mwi(pdev);
        else            pci_clear_mwi(pdev);
 
        /* read result from hardware (in case bit refused to enable) */
@@ -1238,7 +1238,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        };
        static int last_irq;
        static int multiport_cnt;       /* For four-port boards w/one EEPROM */
-       u8 chip_rev;
        int i, irq;
        unsigned short sum;
        unsigned char *ee_data;
@@ -1274,10 +1273,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
 
        if (pdev->vendor == 0x1282 && pdev->device == 0x9100)
        {
-               u32 dev_rev;
                /* Read Chip revision */
-               pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev);
-               if(dev_rev < 0x02000030)
+               if (pdev->revision < 0x02000030)
                {
                        printk(KERN_ERR PFX "skipping early DM9100 with Crc bug (use dmfe)\n");
                        return -ENODEV;
@@ -1360,8 +1357,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        if (!ioaddr)
                goto err_out_free_res;
 
-       pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev);
-
        /*
         * initialize private data structure 'tp'
         * it is zeroed and aligned in alloc_etherdev
@@ -1382,7 +1377,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        tp->flags = tulip_tbl[chip_idx].flags;
        tp->pdev = pdev;
        tp->base_addr = ioaddr;
-       tp->revision = chip_rev;
+       tp->revision = pdev->revision;
        tp->csr0 = csr0;
        spin_lock_init(&tp->lock);
        spin_lock_init(&tp->mii_lock);
@@ -1399,7 +1394,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
                tulip_mwi_config (pdev, dev);
 #else
        /* MWI is broken for DC21143 rev 65... */
-       if (chip_idx == DC21143 && chip_rev == 65)
+       if (chip_idx == DC21143 && pdev->revision == 65)
                tp->csr0 &= ~MWI;
 #endif
 
@@ -1640,7 +1635,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
 #else
                "Port"
 #endif
-               " %#llx,", dev->name, chip_name, chip_rev,
+               " %#llx,", dev->name, chip_name, pdev->revision,
                (unsigned long long) pci_resource_start(pdev, TULIP_BAR));
        pci_set_drvdata(pdev, dev);
 
index 37e35cd277a18818310e7756a15b92c138cde791..16a54e6b8d4f002b31e1a2e967785a1fac538e91 100644 (file)
@@ -205,7 +205,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
 {
        struct net_device *dev = NULL;
        struct xircom_private *private;
-       unsigned char chip_rev;
        unsigned long flags;
        unsigned short tmp16;
        enter("xircom_probe");
@@ -224,8 +223,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
        pci_read_config_word (pdev,PCI_STATUS, &tmp16);
        pci_write_config_word (pdev, PCI_STATUS,tmp16);
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);
-
        if (!request_region(pci_resource_start(pdev, 0), 128, "xircom_cb")) {
                printk(KERN_ERR "xircom_probe: failed to allocate io-region\n");
                return -ENODEV;
@@ -286,7 +283,7 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
                goto reg_fail;
        }
 
-       printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq);
+       printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, pdev->revision, pdev->irq);
        /* start the transmitter to get a heartbeat */
        /* TODO: send 2 dummy packets here */
        transceiver_voodoo(private);
index f984fbde8b23356ab41805a4c0ae773477cc3996..fc439f333350ded1eae790db6268e035e597a876 100644 (file)
@@ -524,7 +524,6 @@ static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_devi
        int chip_idx = id->driver_data;
        long ioaddr;
        int i;
-       u8 chip_rev;
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -620,9 +619,8 @@ static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_devi
        if (register_netdev(dev))
                goto err_out_cleardev;
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);
        printk(KERN_INFO "%s: %s rev %d at %#3lx,",
-              dev->name, xircom_tbl[chip_idx].chip_name, chip_rev, ioaddr);
+              dev->name, xircom_tbl[chip_idx].chip_name, pdev->revision, ioaddr);
        for (i = 0; i < 6; i++)
                printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]);
        printk(", IRQ %d.\n", dev->irq);
index df524548d5314e92731d0913848a9ef22aabaaeb..03587205546e71260ad81c10c76dee6d0674d719 100644 (file)
@@ -2267,12 +2267,6 @@ need_resume:
        typhoon_resume(pdev);
        return -EBUSY;
 }
-
-static int
-typhoon_enable_wake(struct pci_dev *pdev, pci_power_t state, int enable)
-{
-       return pci_enable_wake(pdev, state, enable);
-}
 #endif
 
 static int __devinit
@@ -2636,7 +2630,6 @@ static struct pci_driver typhoon_driver = {
 #ifdef CONFIG_PM
        .suspend        = typhoon_suspend,
        .resume         = typhoon_resume,
-       .enable_wake    = typhoon_enable_wake,
 #endif
 };
 
index 565f6cc185ceccefe0327cf49df0f65b6867b5b1..f51c2c138f1032e64a86bcadd599bb15f77ad7f0 100644 (file)
@@ -622,7 +622,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
        struct net_device *dev;
        struct rhine_private *rp;
        int i, rc;
-       u8 pci_rev;
        u32 quirks;
        long pioaddr;
        long memaddr;
@@ -642,27 +641,25 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
                printk(version);
 #endif
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
        io_size = 256;
        phy_id = 0;
        quirks = 0;
        name = "Rhine";
-       if (pci_rev < VTunknown0) {
+       if (pdev->revision < VTunknown0) {
                quirks = rqRhineI;
                io_size = 128;
        }
-       else if (pci_rev >= VT6102) {
+       else if (pdev->revision >= VT6102) {
                quirks = rqWOL | rqForceReset;
-               if (pci_rev < VT6105) {
+               if (pdev->revision < VT6105) {
                        name = "Rhine II";
                        quirks |= rqStatusWBRace;       /* Rhine-II exclusive */
                }
                else {
                        phy_id = 1;     /* Integrated PHY, phy_id fixed to 1 */
-                       if (pci_rev >= VT6105_B0)
+                       if (pdev->revision >= VT6105_B0)
                                quirks |= rq6patterns;
-                       if (pci_rev < VT6105M)
+                       if (pdev->revision < VT6105M)
                                name = "Rhine III";
                        else
                                name = "Rhine III (Management Adapter)";
index b670b97bcfde488a7de7a2e4bbe47985a0597a22..f331843d1102ac80839e2a46f098a7b2b51d5f67 100644 (file)
@@ -890,8 +890,7 @@ static void __devinit velocity_init_info(struct pci_dev *pdev,
 
 static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
 {
-       if (pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0)
-               return -EIO;
+       vptr->rev_id = pdev->revision;
 
        pci_set_master(pdev);
 
index 999bf71937ca55f5540304242253f51d4ed67ce0..ec1c556a47caf65c69b81504f7a1207e7e52f013 100644 (file)
@@ -3439,7 +3439,6 @@ static int __devinit
 cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int first_time = 1;
-       ucchar cpc_rev_id;
        int err, eeprom_outdated = 0;
        ucshort device_id;
        pc300_t *card;
@@ -3480,7 +3479,6 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        card->hw.falcsize = pci_resource_len(pdev, 4);
        card->hw.plxphys = pci_resource_start(pdev, 5);
        card->hw.plxsize = pci_resource_len(pdev, 5);
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &cpc_rev_id);
 
        switch (device_id) {
                case PCI_DEVICE_ID_PC300_RX_1:
@@ -3498,7 +3496,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 #ifdef PC300_DEBUG_PCI
        printk("cpc (bus=0x0%x,pci_id=0x%x,", pdev->bus->number, pdev->devfn);
-       printk("rev_id=%d) IRQ%d\n", cpc_rev_id, card->hw.irq);
+       printk("rev_id=%d) IRQ%d\n", pdev->revision, card->hw.irq);
        printk("cpc:found  ramaddr=0x%08lx plxaddr=0x%08lx "
               "ctladdr=0x%08lx falcaddr=0x%08lx\n",
               card->hw.ramphys, card->hw.plxphys, card->hw.scaphys,
index aff05dba720ab023983212dba42172ca65b9d53f..dfbd3b00f03b0a524084bcdeecbabded50198067 100644 (file)
@@ -311,7 +311,6 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
                                        const struct pci_device_id *ent)
 {
        card_t *card;
-       u8 rev_id;
        u32 __iomem *p;
        int i;
        u32 ramsize;
@@ -366,7 +365,6 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
                        return -ENOMEM;
                }
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
        if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE ||
            pci_resource_len(pdev, 2) != PC300_SCA_SIZE ||
            pci_resource_len(pdev, 3) < 16384) {
index ca06a00d9d864967c604c1582a346d80d512b367..7f720de2e9f08b4c6de5b6675a30572535d6ceb6 100644 (file)
@@ -289,7 +289,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
                                         const struct pci_device_id *ent)
 {
        card_t *card;
-       u8 rev_id;
        u32 __iomem *p;
        int i;
        u32 ramsize;
@@ -330,7 +329,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
                return -ENOMEM;
        }
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
        if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE ||
            pci_resource_len(pdev, 2) != PCI200SYN_SCA_SIZE ||
            pci_resource_len(pdev, 3) < 16384) {
index ef6b253a92cec27d09039af365888cf18d3783d3..c5d6753a55ea80aa54e051b5d0ab7d671d352b4b 100644 (file)
@@ -3741,10 +3741,8 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
                                  &bcm->board_type);
        if (err)
                goto err_iounmap;
-       err = bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
-                                 &bcm->board_revision);
-       if (err)
-               goto err_iounmap;
+
+       bcm->board_revision = bcm->pci_dev->revision;
 
        err = bcm43xx_chipset_attach(bcm);
        if (err)
index 0cd48d151f5ee950ee9f96e677bcfea140b1f557..7da3664b85156a2541728f2f68ce82d887267d0f 100644 (file)
@@ -453,8 +453,6 @@ static struct pci_driver prism2_pci_drv_id = {
        .suspend        = prism2_pci_suspend,
        .resume         = prism2_pci_resume,
 #endif /* CONFIG_PM */
-       /* Linux 2.4.6 added save_state and enable_wake that are not used here
-        */
 };
 
 
index 0183df757b3ec92df8f71aa64e8e4ec8de084f22..040dc3e364101162bd3e7b511e3527758c1dab65 100644 (file)
@@ -613,9 +613,6 @@ static struct pci_driver prism2_plx_drv_id = {
        .id_table       = prism2_plx_id_table,
        .probe          = prism2_plx_probe,
        .remove         = prism2_plx_remove,
-       .suspend        = NULL,
-       .resume         = NULL,
-       .enable_wake    = NULL
 };
 
 
index 3dcb13bb7d5782c089da59442a15e24cf3c49ba7..af2e4f2405f2577ae0f047d37827c6eb532054f8 100644 (file)
@@ -87,7 +87,6 @@ static struct pci_driver prism54_driver = {
        .remove = prism54_remove,
        .suspend = prism54_suspend,
        .resume = prism54_resume,
-       /* .enable_wake ; we don't support this yet */
 };
 
 /******************************************************************************
@@ -167,8 +166,7 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        pci_set_master(pdev);
 
        /* enable MWI */
-       if (!pci_set_mwi(pdev))
-               printk(KERN_INFO "%s: pci_set_mwi(pdev) succeeded\n", DRV_NAME);
+       pci_try_set_mwi(pdev);
 
        /* setup the network device interface and its structure */
        if (!(ndev = islpci_setup(pdev))) {
index 924ef0609460f4a338e0423101741ab92f96c8e1..fc4bde259dc7a68da93c89640aa36db34f5744e5 100644 (file)
@@ -121,14 +121,14 @@ struct pdcspath_entry pdcspath_entry_##_name = { \
 
 #define PDCS_ATTR(_name, _mode, _show, _store) \
 struct subsys_attribute pdcs_attr_##_name = { \
-       .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+       .attr = {.name = __stringify(_name), .mode = _mode}, \
        .show = _show, \
        .store = _store, \
 };
 
 #define PATHS_ATTR(_name, _mode, _show, _store) \
 struct pdcspath_attribute paths_attr_##_name = { \
-       .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+       .attr = {.name = __stringify(_name), .mode = _mode}, \
        .show = _show, \
        .store = _store, \
 };
index e3beb784406f69019511cebf7d8cd33542ccb99c..006054a409958a5f7617f9b1713a0eced9381d68 100644 (file)
@@ -41,9 +41,7 @@ obj-$(CONFIG_ACPI)    += pci-acpi.o
 # Cardbus & CompactPCI use setup-bus
 obj-$(CONFIG_HOTPLUG) += setup-bus.o
 
-ifndef CONFIG_X86
-obj-y += syscall.o
-endif
+obj-$(CONFIG_PCI_SYSCALL) += syscall.o
 
 ifeq ($(CONFIG_PCI_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
index ddbadd95387ece7340617aae7ffcfbfb9843cca1..f6cc0c5b56572715425a7a535f2c2444c25a0ca6 100644 (file)
@@ -211,6 +211,7 @@ typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
 
 extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
 extern int acpiphp_disable_slot (struct acpiphp_slot *slot);
+extern int acpiphp_eject_slot (struct acpiphp_slot *slot);
 extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);
 extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);
 extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
index fa5c0197d571c81325ace3d08d2e6c7246fa74a9..a0ca63adad5ac41c3df29fc7171b814d5db4709a 100644 (file)
@@ -156,11 +156,15 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
        struct slot *slot = hotplug_slot->private;
+       int retval;
 
        dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
        /* disable the specified slot */
-       return acpiphp_disable_slot(slot->acpi_slot);
+       retval = acpiphp_disable_slot(slot->acpi_slot);
+       if (!retval)
+               retval = acpiphp_eject_slot(slot->acpi_slot);
+       return retval;
 }
 
 
index 9ef4e989afc43b0fc70153258ebb91821aaff82a..1e125b56c9a97ccba476eed8566b04fedaf3cd01 100644 (file)
@@ -1282,7 +1282,7 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
 /**
  * acpiphp_eject_slot - physically eject the slot
  */
-static int acpiphp_eject_slot(struct acpiphp_slot *slot)
+int acpiphp_eject_slot(struct acpiphp_slot *slot)
 {
        acpi_status status;
        struct acpiphp_func *func;
@@ -1368,6 +1368,9 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
                        (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
                return;
 
+       if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+               return;
+
        pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
                        bridge->hpp.t0->cache_line_size);
        pci_write_config_byte(dev, PCI_LATENCY_TIMER,
@@ -1502,6 +1505,37 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type)
  * ACPI event handlers
  */
 
+static acpi_status
+count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       int *count = (int *)context;
+       struct acpiphp_bridge *bridge;
+
+       bridge = acpiphp_handle_to_bridge(handle);
+       if (bridge)
+               (*count)++;
+       return AE_OK ;
+}
+
+static acpi_status
+check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       struct acpiphp_bridge *bridge;
+       char objname[64];
+       struct acpi_buffer buffer = { .length = sizeof(objname),
+                                     .pointer = objname };
+
+       bridge = acpiphp_handle_to_bridge(handle);
+       if (bridge) {
+               acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+               dbg("%s: re-enumerating slots under %s\n",
+                       __FUNCTION__, objname);
+               acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+               acpiphp_check_bridge(bridge);
+       }
+       return AE_OK ;
+}
+
 /**
  * handle_hotplug_event_bridge - handle ACPI event on bridges
  *
@@ -1519,6 +1553,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
        struct acpi_buffer buffer = { .length = sizeof(objname),
                                      .pointer = objname };
        struct acpi_device *device;
+       int num_sub_bridges = 0;
 
        if (acpi_bus_get_device(handle, &device)) {
                /* This bridge must have just been physically inserted */
@@ -1527,7 +1562,12 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
        }
 
        bridge = acpiphp_handle_to_bridge(handle);
-       if (!bridge) {
+       if (type == ACPI_NOTIFY_BUS_CHECK) {
+               acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
+                       count_sub_bridges, &num_sub_bridges, NULL);
+       }
+
+       if (!bridge && !num_sub_bridges) {
                err("cannot get bridge info\n");
                return;
        }
@@ -1538,7 +1578,14 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
        case ACPI_NOTIFY_BUS_CHECK:
                /* bus re-enumerate */
                dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
-               acpiphp_check_bridge(bridge);
+               if (bridge) {
+                       dbg("%s: re-enumerating slots under %s\n",
+                               __FUNCTION__, objname);
+                       acpiphp_check_bridge(bridge);
+               }
+               if (num_sub_bridges)
+                       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+                               ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL);
                break;
 
        case ACPI_NOTIFY_DEVICE_CHECK:
index e7322c25d377e65949722fd1f71b04edabb957d2..70db38c0ced9f6586ed6356e4bc8ef78c6cd4235 100644 (file)
@@ -106,7 +106,8 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status);
 static void ibm_handle_events(acpi_handle handle, u32 event, void *context);
 static int ibm_get_table_from_acpi(char **bufp);
 static ssize_t ibm_read_apci_table(struct kobject *kobj,
-               char *buffer, loff_t pos, size_t size);
+                                  struct bin_attribute *bin_attr,
+                                  char *buffer, loff_t pos, size_t size);
 static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
                u32 lvl, void *context, void **rv);
 static int __init ibm_acpiphp_init(void);
@@ -117,7 +118,6 @@ static struct notification ibm_note;
 static struct bin_attribute ibm_apci_table_attr = {
            .attr = {
                    .name = "apci_table",
-                   .owner = THIS_MODULE,
                    .mode = S_IRUGO,
            },
            .read = ibm_read_apci_table,
@@ -358,7 +358,8 @@ read_table_done:
  * our solution is to only allow reading the table in all at once
  **/
 static ssize_t ibm_read_apci_table(struct kobject *kobj,
-               char *buffer, loff_t pos, size_t size)
+                                  struct bin_attribute *bin_attr,
+                                  char *buffer, loff_t pos, size_t size)
 {
        int bytes_read = -EINVAL;
        char *table = NULL;
index 684551559d4420b7b9f436ee879ceb75cf15a296..ed4d44e3332c1fd38fcbd535b206fca54586c81d 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/smp_lock.h>
 #include <asm/atomic.h>
 #include <linux/delay.h>
+#include <linux/kthread.h>
 #include "cpci_hotplug.h"
 
 #define DRIVER_AUTHOR  "Scott Murray <scottm@somanetworks.com>"
@@ -59,9 +60,8 @@ static int slots;
 static atomic_t extracting;
 int cpci_debug;
 static struct cpci_hp_controller *controller;
-static struct semaphore event_semaphore;       /* mutex for process loop (up if something to process) */
-static struct semaphore thread_exit;           /* guard ensure thread has exited before calling it quits */
-static int thread_finished = 1;
+static struct task_struct *cpci_thread;
+static int thread_finished;
 
 static int enable_slot(struct hotplug_slot *slot);
 static int disable_slot(struct hotplug_slot *slot);
@@ -357,9 +357,7 @@ cpci_hp_intr(int irq, void *data)
        controller->ops->disable_irq();
 
        /* Trigger processing by the event thread */
-       dbg("Signal event_semaphore");
-       up(&event_semaphore);
-       dbg("exited cpci_hp_intr");
+       wake_up_process(cpci_thread);
        return IRQ_HANDLED;
 }
 
@@ -521,17 +519,12 @@ event_thread(void *data)
 {
        int rc;
 
-       lock_kernel();
-       daemonize("cpci_hp_eventd");
-       unlock_kernel();
-
        dbg("%s - event thread started", __FUNCTION__);
        while (1) {
                dbg("event thread sleeping");
-               down_interruptible(&event_semaphore);
-               dbg("event thread woken, thread_finished = %d",
-                   thread_finished);
-               if (thread_finished || signal_pending(current))
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
+               if (kthread_should_stop())
                        break;
                do {
                        rc = check_slots();
@@ -541,18 +534,17 @@ event_thread(void *data)
                        } else if (rc < 0) {
                                dbg("%s - error checking slots", __FUNCTION__);
                                thread_finished = 1;
-                               break;
+                               goto out;
                        }
-               } while (atomic_read(&extracting) && !thread_finished);
-               if (thread_finished)
+               } while (atomic_read(&extracting) && !kthread_should_stop());
+               if (kthread_should_stop())
                        break;
 
                /* Re-enable ENUM# interrupt */
                dbg("%s - re-enabling irq", __FUNCTION__);
                controller->ops->enable_irq();
        }
-       dbg("%s - event thread signals exit", __FUNCTION__);
-       up(&thread_exit);
+ out:
        return 0;
 }
 
@@ -562,12 +554,8 @@ poll_thread(void *data)
 {
        int rc;
 
-       lock_kernel();
-       daemonize("cpci_hp_polld");
-       unlock_kernel();
-
        while (1) {
-               if (thread_finished || signal_pending(current))
+               if (kthread_should_stop() || signal_pending(current))
                        break;
                if (controller->ops->query_enum()) {
                        do {
@@ -578,48 +566,36 @@ poll_thread(void *data)
                                } else if (rc < 0) {
                                        dbg("%s - error checking slots", __FUNCTION__);
                                        thread_finished = 1;
-                                       break;
+                                       goto out;
                                }
-                       } while (atomic_read(&extracting) && !thread_finished);
+                       } while (atomic_read(&extracting) && !kthread_should_stop());
                }
                msleep(100);
        }
-       dbg("poll thread signals exit");
-       up(&thread_exit);
+ out:
        return 0;
 }
 
 static int
 cpci_start_thread(void)
 {
-       int pid;
-
-       /* initialize our semaphores */
-       init_MUTEX_LOCKED(&event_semaphore);
-       init_MUTEX_LOCKED(&thread_exit);
-       thread_finished = 0;
-
        if (controller->irq)
-               pid = kernel_thread(event_thread, NULL, 0);
+               cpci_thread = kthread_run(event_thread, NULL, "cpci_hp_eventd");
        else
-               pid = kernel_thread(poll_thread, NULL, 0);
-       if (pid < 0) {
+               cpci_thread = kthread_run(poll_thread, NULL, "cpci_hp_polld");
+       if (IS_ERR(cpci_thread)) {
                err("Can't start up our thread");
-               return -1;
+               return PTR_ERR(cpci_thread);
        }
-       dbg("Our thread pid = %d", pid);
+       thread_finished = 0;
        return 0;
 }
 
 static void
 cpci_stop_thread(void)
 {
+       kthread_stop(cpci_thread);
        thread_finished = 1;
-       dbg("thread finish command given");
-       if (controller->irq)
-               up(&event_semaphore);
-       dbg("wait for thread to exit");
-       down(&thread_exit);
 }
 
 int
index 7b1beaad2752ef731a41e2be9d91e5189ce41fe8..5e9be44817cb5ff4daa3f8bc5b04f6f45f10e6d3 100644 (file)
@@ -45,8 +45,6 @@ extern int cpci_debug;
 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
 
-#define ROUND_UP(x, a)         (((x) + (a) - 1) & ~((a) - 1))
-
 
 u8 cpci_get_attention_status(struct slot* slot)
 {
index 5617cfdadc5c64b19b49a08c041b28fb78c52919..d590a99930fa5a762f2d327faca4d10ecb7373d3 100644 (file)
@@ -796,7 +796,6 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        u8 num_of_slots = 0;
        u8 hp_slot = 0;
        u8 device;
-       u8 rev;
        u8 bus_cap;
        u16 temp_word;
        u16 vendor_id;
@@ -823,9 +822,8 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
        dbg("Vendor ID: %x\n", vendor_id);
 
-       rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-       dbg("revision: %d\n", rev);
-       if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
+       dbg("revision: %d\n", pdev->revision);
+       if ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!pdev->revision)) {
                err(msg_HPC_rev_error);
                rc = -ENODEV;
                goto err_disable_device;
@@ -836,7 +834,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * For Intel, each SSID bit identifies a PHP capability.
         * Also Intel HPC's may have RID=0.
         */
-       if ((rev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
+       if ((pdev->revision > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
                // TODO: This code can be made to support non-Compaq or Intel subsystem IDs
                rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
                if (rc) {
@@ -870,7 +868,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
                switch (subsystem_vid) {
                        case PCI_VENDOR_ID_COMPAQ:
-                               if (rev >= 0x13) { /* CIOBX */
+                               if (pdev->revision >= 0x13) { /* CIOBX */
                                        ctrl->push_flag = 1;
                                        ctrl->slot_switch_type = 1;
                                        ctrl->push_button = 1;
@@ -1075,7 +1073,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        memcpy(ctrl->pci_bus, pdev->bus, sizeof(*ctrl->pci_bus));
 
        ctrl->bus = pdev->bus->number;
-       ctrl->rev = rev;
+       ctrl->rev = pdev->revision;
        dbg("bus device function rev: %d %d %d %d\n", ctrl->bus,
                PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev);
 
index ccc57627201eecaf56bff44a4a7826b6ac88e68f..7959c222dc24e939c7734fc201fab8491004a3b0 100644 (file)
@@ -103,6 +103,7 @@ struct controller {
        u8 cap_base;
        struct timer_list poll_timer;
        volatile int cmd_busy;
+       spinlock_t lock;
 };
 
 #define INT_BUTTON_IGNORE              0
index 7f22caa70178c5d74393f5f9ca2a18e94c296435..98e541ffef3d5f9ae0d90d91f5c66b358bfc4783 100644 (file)
@@ -197,6 +197,12 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
                            __FUNCTION__);
                        return;
                }
+               /*
+                * After turning power off, we must wait for at least
+                * 1 second before taking any action that relies on
+                * power having been removed from the slot/adapter.
+                */
+               msleep(1000);
        }
 }
 
@@ -615,6 +621,12 @@ int pciehp_disable_slot(struct slot *p_slot)
                        mutex_unlock(&p_slot->ctrl->crit_sect);
                        return -EINVAL;
                }
+               /*
+                * After turning power off, we must wait for at least
+                * 1 second before taking any action that relies on
+                * power having been removed from the slot/adapter.
+                */
+               msleep(1000);
        }
 
        ret = remove_board(p_slot);
index 9aac6a87eb5393f01bc1c7e15956d1efdbb9b5b9..016eea94a8a5729d1cf6e5908a2c6a205d4b6149 100644 (file)
@@ -275,11 +275,19 @@ static inline int pcie_wait_cmd(struct controller *ctrl)
        return retval;
 }
 
-static int pcie_write_cmd(struct slot *slot, u16 cmd)
+/**
+ * pcie_write_cmd - Issue controller command
+ * @slot: slot to which the command is issued
+ * @cmd:  command value written to slot control register
+ * @mask: bitmask of slot control register to be modified
+ */
+static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
 {
        struct controller *ctrl = slot->ctrl;
        int retval = 0;
        u16 slot_status;
+       u16 slot_ctrl;
+       unsigned long flags;
 
        DBG_ENTER_ROUTINE 
 
@@ -299,17 +307,29 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
                    __FUNCTION__);
        }
 
-       ctrl->cmd_busy = 1;
-       retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE));
+       spin_lock_irqsave(&ctrl->lock, flags);
+       retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
        if (retval) {
-               err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
-               goto out;
+               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+               goto out_spin_unlock;
        }
 
+       slot_ctrl &= ~mask;
+       slot_ctrl |= ((cmd & mask) | CMD_CMPL_INTR_ENABLE);
+
+       ctrl->cmd_busy = 1;
+       retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
+       if (retval)
+               err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+
+ out_spin_unlock:
+       spin_unlock_irqrestore(&ctrl->lock, flags);
+
        /*
         * Wait for command completion.
         */
-       retval = pcie_wait_cmd(ctrl);
+       if (!retval)
+               retval = pcie_wait_cmd(ctrl);
  out:
        mutex_unlock(&ctrl->ctrl_lock);
        DBG_LEAVE_ROUTINE 
@@ -502,25 +522,20 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status)
 
 static int hpc_toggle_emi(struct slot *slot)
 {
-       struct controller *ctrl = slot->ctrl;
-       u16 slot_cmd = 0;
-       u16 slot_ctrl;
-       int rc = 0;
+       u16 slot_cmd;
+       u16 cmd_mask;
+       int rc;
 
        DBG_ENTER_ROUTINE
 
-       rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-       if (rc) {
-               err("%s : hp_register_read_word SLOT_CTRL failed\n",
-                       __FUNCTION__);
-               return rc;
-       }
-
-       slot_cmd = (slot_ctrl | EMI_CTRL);
-       if (!pciehp_poll_mode)
+       slot_cmd = EMI_CTRL;
+       cmd_mask = EMI_CTRL;
+       if (!pciehp_poll_mode) {
                slot_cmd = slot_cmd | HP_INTR_ENABLE;
+               cmd_mask = cmd_mask | HP_INTR_ENABLE;
+       }
 
-       pcie_write_cmd(slot, slot_cmd);
+       rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
        slot->last_emi_toggle = get_seconds();
        DBG_LEAVE_ROUTINE
        return rc;
@@ -529,35 +544,32 @@ static int hpc_toggle_emi(struct slot *slot)
 static int hpc_set_attention_status(struct slot *slot, u8 value)
 {
        struct controller *ctrl = slot->ctrl;
-       u16 slot_cmd = 0;
-       u16 slot_ctrl;
-       int rc = 0;
+       u16 slot_cmd;
+       u16 cmd_mask;
+       int rc;
 
        DBG_ENTER_ROUTINE
 
-       rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               return rc;
-       }
-
+       cmd_mask = ATTN_LED_CTRL;
        switch (value) {
                case 0 :        /* turn off */
-                       slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x00C0;
+                       slot_cmd = 0x00C0;
                        break;
                case 1:         /* turn on */
-                       slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040;
+                       slot_cmd = 0x0040;
                        break;
                case 2:         /* turn blink */
-                       slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080;
+                       slot_cmd = 0x0080;
                        break;
                default:
                        return -1;
        }
-       if (!pciehp_poll_mode)
-               slot_cmd = slot_cmd | HP_INTR_ENABLE; 
+       if (!pciehp_poll_mode) {
+               slot_cmd = slot_cmd | HP_INTR_ENABLE;
+               cmd_mask = cmd_mask | HP_INTR_ENABLE;
+       }
 
-       pcie_write_cmd(slot, slot_cmd);
+       rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
        dbg("%s: SLOTCTRL %x write cmd %x\n",
            __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
        
@@ -570,21 +582,18 @@ static void hpc_set_green_led_on(struct slot *slot)
 {
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
-       u16 slot_ctrl;
-       int rc = 0;
+       u16 cmd_mask;
                
        DBG_ENTER_ROUTINE
 
-       rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               return;
+       slot_cmd = 0x0100;
+       cmd_mask = PWR_LED_CTRL;
+       if (!pciehp_poll_mode) {
+               slot_cmd = slot_cmd | HP_INTR_ENABLE;
+               cmd_mask = cmd_mask | HP_INTR_ENABLE;
        }
-       slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
-       if (!pciehp_poll_mode)
-               slot_cmd = slot_cmd | HP_INTR_ENABLE; 
 
-       pcie_write_cmd(slot, slot_cmd);
+       pcie_write_cmd(slot, slot_cmd, cmd_mask);
 
        dbg("%s: SLOTCTRL %x write cmd %x\n",
            __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -596,22 +605,18 @@ static void hpc_set_green_led_off(struct slot *slot)
 {
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
-       u16 slot_ctrl;
-       int rc = 0;
+       u16 cmd_mask;
 
        DBG_ENTER_ROUTINE
 
-       rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               return;
+       slot_cmd = 0x0300;
+       cmd_mask = PWR_LED_CTRL;
+       if (!pciehp_poll_mode) {
+               slot_cmd = slot_cmd | HP_INTR_ENABLE;
+               cmd_mask = cmd_mask | HP_INTR_ENABLE;
        }
 
-       slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300;
-
-       if (!pciehp_poll_mode)
-               slot_cmd = slot_cmd | HP_INTR_ENABLE; 
-       pcie_write_cmd(slot, slot_cmd);
+       pcie_write_cmd(slot, slot_cmd, cmd_mask);
        dbg("%s: SLOTCTRL %x write cmd %x\n",
            __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 
@@ -623,22 +628,18 @@ static void hpc_set_green_led_blink(struct slot *slot)
 {
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
-       u16 slot_ctrl;
-       int rc = 0; 
+       u16 cmd_mask;
        
        DBG_ENTER_ROUTINE
 
-       rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               return;
+       slot_cmd = 0x0200;
+       cmd_mask = PWR_LED_CTRL;
+       if (!pciehp_poll_mode) {
+               slot_cmd = slot_cmd | HP_INTR_ENABLE;
+               cmd_mask = cmd_mask | HP_INTR_ENABLE;
        }
 
-       slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200;
-
-       if (!pciehp_poll_mode)
-               slot_cmd = slot_cmd | HP_INTR_ENABLE; 
-       pcie_write_cmd(slot, slot_cmd);
+       pcie_write_cmd(slot, slot_cmd, cmd_mask);
 
        dbg("%s: SLOTCTRL %x write cmd %x\n",
            __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -669,7 +670,8 @@ static int hpc_power_on_slot(struct slot * slot)
 {
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
-       u16 slot_ctrl, slot_status;
+       u16 cmd_mask;
+       u16 slot_status;
        int retval = 0;
 
        DBG_ENTER_ROUTINE 
@@ -692,23 +694,23 @@ static int hpc_power_on_slot(struct slot * slot)
                }
        }
 
-       retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-       if (retval) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               return retval;
-       }
-
-       slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
-
+       slot_cmd = POWER_ON;
+       cmd_mask = PWR_CTRL;
        /* Enable detection that we turned off at slot power-off time */
-       if (!pciehp_poll_mode)
+       if (!pciehp_poll_mode) {
                slot_cmd = slot_cmd |
                           PWR_FAULT_DETECT_ENABLE |
                           MRL_DETECT_ENABLE |
                           PRSN_DETECT_ENABLE |
                           HP_INTR_ENABLE;
+               cmd_mask = cmd_mask |
+                          PWR_FAULT_DETECT_ENABLE |
+                          MRL_DETECT_ENABLE |
+                          PRSN_DETECT_ENABLE |
+                          HP_INTR_ENABLE;
+       }
 
-       retval = pcie_write_cmd(slot, slot_cmd);
+       retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
 
        if (retval) {
                err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
@@ -726,21 +728,15 @@ static int hpc_power_off_slot(struct slot * slot)
 {
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
-       u16 slot_ctrl;
+       u16 cmd_mask;
        int retval = 0;
 
        DBG_ENTER_ROUTINE 
 
        dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
 
-       retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-       if (retval) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               return retval;
-       }
-
-       slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
-
+       slot_cmd = POWER_OFF;
+       cmd_mask = PWR_CTRL;
        /*
         * If we get MRL or presence detect interrupts now, the isr
         * will notice the sticky power-fault bit too and issue power
@@ -748,14 +744,19 @@ static int hpc_power_off_slot(struct slot * slot)
         * of command completions, since the power-fault bit remains on
         * till the slot is powered on again.
         */
-       if (!pciehp_poll_mode)
+       if (!pciehp_poll_mode) {
                slot_cmd = (slot_cmd &
                            ~PWR_FAULT_DETECT_ENABLE &
                            ~MRL_DETECT_ENABLE &
                            ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE;
+               cmd_mask = cmd_mask |
+                          PWR_FAULT_DETECT_ENABLE |
+                          MRL_DETECT_ENABLE |
+                          PRSN_DETECT_ENABLE |
+                          HP_INTR_ENABLE;
+       }
 
-       retval = pcie_write_cmd(slot, slot_cmd);
-
+       retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
        if (retval) {
                err("%s: Write command failed!\n", __FUNCTION__);
                return -1;
@@ -775,6 +776,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
        u16 temp_word;
        int hp_slot = 0;        /* only 1 slot per PCI Express port */
        int rc = 0;
+       unsigned long flags;
 
        rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
        if (rc) {
@@ -794,10 +796,12 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
        dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
        /* Mask Hot-plug Interrupt Enable */
        if (!pciehp_poll_mode) {
+               spin_lock_irqsave(&ctrl->lock, flags);
                rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
                if (rc) {
                        err("%s: Cannot read SLOT_CTRL register\n",
                            __FUNCTION__);
+                       spin_unlock_irqrestore(&ctrl->lock, flags);
                        return IRQ_NONE;
                }
 
@@ -808,8 +812,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                if (rc) {
                        err("%s: Cannot write to SLOTCTRL register\n",
                            __FUNCTION__);
+                       spin_unlock_irqrestore(&ctrl->lock, flags);
                        return IRQ_NONE;
                }
+               spin_unlock_irqrestore(&ctrl->lock, flags);
 
                rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
                if (rc) {
@@ -859,10 +865,12 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
        }
        /* Unmask Hot-plug Interrupt Enable */
        if (!pciehp_poll_mode) {
+               spin_lock_irqsave(&ctrl->lock, flags);
                rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
                if (rc) {
                        err("%s: Cannot read SLOTCTRL register\n",
                            __FUNCTION__);
+                       spin_unlock_irqrestore(&ctrl->lock, flags);
                        return IRQ_NONE;
                }
 
@@ -873,8 +881,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                if (rc) {
                        err("%s: Cannot write to SLOTCTRL register\n",
                            __FUNCTION__);
+                       spin_unlock_irqrestore(&ctrl->lock, flags);
                        return IRQ_NONE;
                }
+               spin_unlock_irqrestore(&ctrl->lock, flags);
 
                rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
                if (rc) {
@@ -1237,6 +1247,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 
        mutex_init(&ctrl->crit_sect);
        mutex_init(&ctrl->ctrl_lock);
+       spin_lock_init(&ctrl->lock);
 
        /* setup wait queue */
        init_waitqueue_head(&ctrl->queue);
index b5ac810404c0f19dc98318dfe8dde6212d04c2bb..c8062494009f8fdb692adbbe15bb741a870064cd 100644 (file)
@@ -55,8 +55,6 @@ acpi_query_osc (
 
        status = acpi_evaluate_object(handle, "_OSC", &input, &output);
        if (ACPI_FAILURE (status)) {
-               printk(KERN_DEBUG  
-                       "Evaluate _OSC Set fails. Status = 0x%04x\n", status);
                *ret_status = status;
                return status;
        }
@@ -124,11 +122,9 @@ acpi_run_osc (
        in_params[3].buffer.pointer     = (u8 *)context;
 
        status = acpi_evaluate_object(handle, "_OSC", &input, &output);
-       if (ACPI_FAILURE (status)) {
-               printk(KERN_DEBUG  
-                       "Evaluate _OSC Set fails. Status = 0x%04x\n", status);
+       if (ACPI_FAILURE (status))
                return status;
-       }
+
        out_obj = output.pointer;
        if (out_obj->type != ACPI_TYPE_BUFFER) {
                printk(KERN_DEBUG  
index 284e83a527f9d4564c916597f6d65b21b2cff08c..10dbdec80416dc69ce9272e37c0fbe7127d328a6 100644 (file)
@@ -213,7 +213,8 @@ struct device_attribute pci_dev_attrs[] = {
 };
 
 static ssize_t
-pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+               char *buf, loff_t off, size_t count)
 {
        struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
        unsigned int size = 64;
@@ -285,7 +286,8 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
 }
 
 static ssize_t
-pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+                char *buf, loff_t off, size_t count)
 {
        struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
        unsigned int size = count;
@@ -352,7 +354,8 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
  * callback routine (pci_legacy_read).
  */
 ssize_t
-pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
+                  char *buf, loff_t off, size_t count)
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
                                                       struct class_device,
@@ -376,7 +379,8 @@ pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
  * callback routine (pci_legacy_write).
  */
 ssize_t
-pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
+                   char *buf, loff_t off, size_t count)
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
                                                      struct class_device,
@@ -499,7 +503,6 @@ static int pci_create_resource_files(struct pci_dev *pdev)
                        sprintf(res_attr_name, "resource%d", i);
                        res_attr->attr.name = res_attr_name;
                        res_attr->attr.mode = S_IRUSR | S_IWUSR;
-                       res_attr->attr.owner = THIS_MODULE;
                        res_attr->size = pci_resource_len(pdev, i);
                        res_attr->mmap = pci_mmap_resource;
                        res_attr->private = &pdev->resource[i];
@@ -529,7 +532,8 @@ static inline void pci_remove_resource_files(struct pci_dev *dev) { return; }
  * writing anything except 0 enables it
  */
 static ssize_t
-pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
+             char *buf, loff_t off, size_t count)
 {
        struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
 
@@ -552,7 +556,8 @@ pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
  * device corresponding to @kobj.
  */
 static ssize_t
-pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
+            char *buf, loff_t off, size_t count)
 {
        struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
        void __iomem *rom;
@@ -582,7 +587,6 @@ static struct bin_attribute pci_config_attr = {
        .attr = {
                .name = "config",
                .mode = S_IRUGO | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = 256,
        .read = pci_read_config,
@@ -593,13 +597,17 @@ static struct bin_attribute pcie_config_attr = {
        .attr = {
                .name = "config",
                .mode = S_IRUGO | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = 4096,
        .read = pci_read_config,
        .write = pci_write_config,
 };
 
+int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
+{
+       return 0;
+}
+
 int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
        struct bin_attribute *rom_attr = NULL;
@@ -628,7 +636,6 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
                        rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
                        rom_attr->attr.name = "rom";
                        rom_attr->attr.mode = S_IRUSR;
-                       rom_attr->attr.owner = THIS_MODULE;
                        rom_attr->read = pci_read_rom;
                        rom_attr->write = pci_write_rom;
                        retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
@@ -640,10 +647,14 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
                }
        }
        /* add platform-specific attributes */
-       pcibios_add_platform_entries(pdev);
+       if (pcibios_add_platform_entries(pdev))
+               goto err_rom_file;
 
        return 0;
 
+err_rom_file:
+       if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+               sysfs_remove_bin_file(&pdev->dev.kobj, rom_attr);
 err_rom:
        kfree(rom_attr);
 err_resource_files:
index fd47ac0c4730a96080e22151ed186c1ec4585725..03fd59e80fef5726c73a16f1582f4fd8dbf16836 100644 (file)
@@ -406,6 +406,13 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
        if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev))
                return 0;
 
+       /* find PCI PM capability in list */
+       pm = pci_find_capability(dev, PCI_CAP_ID_PM);
+
+       /* abort if the device doesn't support PM capabilities */
+       if (!pm)
+               return -EIO;
+
        /* Validate current state:
         * Can enter D0 from any state, but if we can only go deeper 
         * to sleep if we're already in a low power state
@@ -418,13 +425,6 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
                return 0;        /* we're already there */
 
 
-       /* find PCI PM capability in list */
-       pm = pci_find_capability(dev, PCI_CAP_ID_PM);
-       
-       /* abort if the device doesn't support PM capabilities */
-       if (!pm)
-               return -EIO; 
-
        pci_read_config_word(dev,pm + PCI_PM_PMC,&pmc);
        if ((pmc & PCI_PM_CAP_VER_MASK) > 3) {
                printk(KERN_DEBUG
@@ -1186,6 +1186,11 @@ int pci_set_mwi(struct pci_dev *dev)
        return 0;
 }
 
+int pci_try_set_mwi(struct pci_dev *dev)
+{
+       return 0;
+}
+
 void pci_clear_mwi(struct pci_dev *dev)
 {
 }
@@ -1242,9 +1247,7 @@ pci_set_cacheline_size(struct pci_dev *dev)
  * pci_set_mwi - enables memory-write-invalidate PCI transaction
  * @dev: the PCI device for which MWI is enabled
  *
- * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND,
- * and then calls @pcibios_set_mwi to do the needed arch specific
- * operations or a generic mwi-prep function.
+ * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND.
  *
  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
  */
@@ -1260,7 +1263,8 @@ pci_set_mwi(struct pci_dev *dev)
 
        pci_read_config_word(dev, PCI_COMMAND, &cmd);
        if (! (cmd & PCI_COMMAND_INVALIDATE)) {
-               pr_debug("PCI: Enabling Mem-Wr-Inval for device %s\n", pci_name(dev));
+               pr_debug("PCI: Enabling Mem-Wr-Inval for device %s\n",
+                       pci_name(dev));
                cmd |= PCI_COMMAND_INVALIDATE;
                pci_write_config_word(dev, PCI_COMMAND, cmd);
        }
@@ -1268,6 +1272,21 @@ pci_set_mwi(struct pci_dev *dev)
        return 0;
 }
 
+/**
+ * pci_try_set_mwi - enables memory-write-invalidate PCI transaction
+ * @dev: the PCI device for which MWI is enabled
+ *
+ * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND.
+ * Callers are not required to check the return value.
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+int pci_try_set_mwi(struct pci_dev *dev)
+{
+       int rc = pci_set_mwi(dev);
+       return rc;
+}
+
 /**
  * pci_clear_mwi - disables Memory-Write-Invalidate for device dev
  * @dev: the PCI device to disable
@@ -1374,6 +1393,164 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
 }
 #endif
 
+/**
+ * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
+ * @dev: PCI device to query
+ *
+ * Returns mmrbc: maximum designed memory read count in bytes
+ *    or appropriate error value.
+ */
+int pcix_get_max_mmrbc(struct pci_dev *dev)
+{
+       int err, cap;
+       u32 stat;
+
+       cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+       if (!cap)
+               return -EINVAL;
+
+       err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat);
+       if (err)
+               return -EINVAL;
+
+       return (stat & PCI_X_STATUS_MAX_READ) >> 12;
+}
+EXPORT_SYMBOL(pcix_get_max_mmrbc);
+
+/**
+ * pcix_get_mmrbc - get PCI-X maximum memory read byte count
+ * @dev: PCI device to query
+ *
+ * Returns mmrbc: maximum memory read count in bytes
+ *    or appropriate error value.
+ */
+int pcix_get_mmrbc(struct pci_dev *dev)
+{
+       int ret, cap;
+       u32 cmd;
+
+       cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+       if (!cap)
+               return -EINVAL;
+
+       ret = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd);
+       if (!ret)
+               ret = 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2);
+
+       return ret;
+}
+EXPORT_SYMBOL(pcix_get_mmrbc);
+
+/**
+ * pcix_set_mmrbc - set PCI-X maximum memory read byte count
+ * @dev: PCI device to query
+ * @mmrbc: maximum memory read count in bytes
+ *    valid values are 512, 1024, 2048, 4096
+ *
+ * If possible sets maximum memory read byte count, some bridges have erratas
+ * that prevent this.
+ */
+int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc)
+{
+       int cap, err = -EINVAL;
+       u32 stat, cmd, v, o;
+
+       if (mmrbc < 512 || mmrbc > 4096 || (mmrbc & (mmrbc-1)))
+               goto out;
+
+       v = ffs(mmrbc) - 10;
+
+       cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+       if (!cap)
+               goto out;
+
+       err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat);
+       if (err)
+               goto out;
+
+       if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21)
+               return -E2BIG;
+
+       err = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd);
+       if (err)
+               goto out;
+
+       o = (cmd & PCI_X_CMD_MAX_READ) >> 2;
+       if (o != v) {
+               if (v > o && dev->bus &&
+                  (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MMRBC))
+                       return -EIO;
+
+               cmd &= ~PCI_X_CMD_MAX_READ;
+               cmd |= v << 2;
+               err = pci_write_config_dword(dev, cap + PCI_X_CMD, cmd);
+       }
+out:
+       return err;
+}
+EXPORT_SYMBOL(pcix_set_mmrbc);
+
+/**
+ * pcie_get_readrq - get PCI Express read request size
+ * @dev: PCI device to query
+ *
+ * Returns maximum memory read request in bytes
+ *    or appropriate error value.
+ */
+int pcie_get_readrq(struct pci_dev *dev)
+{
+       int ret, cap;
+       u16 ctl;
+
+       cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!cap)
+               return -EINVAL;
+
+       ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+       if (!ret)
+       ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12);
+
+       return ret;
+}
+EXPORT_SYMBOL(pcie_get_readrq);
+
+/**
+ * pcie_set_readrq - set PCI Express maximum memory read request
+ * @dev: PCI device to query
+ * @count: maximum memory read count in bytes
+ *    valid values are 128, 256, 512, 1024, 2048, 4096
+ *
+ * If possible sets maximum read byte count
+ */
+int pcie_set_readrq(struct pci_dev *dev, int rq)
+{
+       int cap, err = -EINVAL;
+       u16 ctl, v;
+
+       if (rq < 128 || rq > 4096 || (rq & (rq-1)))
+               goto out;
+
+       v = (ffs(rq) - 8) << 12;
+
+       cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!cap)
+               goto out;
+
+       err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+       if (err)
+               goto out;
+
+       if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) {
+               ctl &= ~PCI_EXP_DEVCTL_READRQ;
+               ctl |= v;
+               err = pci_write_config_dword(dev, cap + PCI_EXP_DEVCTL, ctl);
+       }
+
+out:
+       return err;
+}
+EXPORT_SYMBOL(pcie_set_readrq);
+
 /**
  * pci_select_bars - Make BAR mask from the type of resource
  * @dev: the PCI device for which BAR mask is made
@@ -1442,6 +1619,7 @@ EXPORT_SYMBOL(pci_release_selected_regions);
 EXPORT_SYMBOL(pci_request_selected_regions);
 EXPORT_SYMBOL(pci_set_master);
 EXPORT_SYMBOL(pci_set_mwi);
+EXPORT_SYMBOL(pci_try_set_mwi);
 EXPORT_SYMBOL(pci_clear_mwi);
 EXPORT_SYMBOL_GPL(pci_intx);
 EXPORT_SYMBOL(pci_set_dma_mask);
index 3f37a60a6438218245dfdac675d42da21bce511c..c3bde588aa13db4d814785ee24e7bfe86ef4c6c6 100644 (file)
@@ -4,7 +4,7 @@
 
 config PCIEAER
        boolean "Root Port Advanced Error Reporting support"
-       depends on PCIEPORTBUS && ACPI
+       depends on PCIEPORTBUS
        default y
        help
          This enables PCI Express Root Port Advanced Error Reporting
index 15a4f40d520b35eccc6457c40d43653df7922953..8da3bd8455a882b334cf8d843fa4846cc9153fe3 100644 (file)
@@ -4,5 +4,6 @@
 
 obj-$(CONFIG_PCIEAER) += aerdriver.o
 
-aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o aerdrv_acpi.o
+aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o
+aerdriver-$(CONFIG_ACPI) += aerdrv_acpi.o
 
index db6ad8e763ac91dd7d86a4ab55469e1e1dd8128b..6846fb42b399313202ae019fecddb58d3c27eac0 100644 (file)
@@ -157,7 +157,7 @@ static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev)
         * Initialize Root lock access, e_lock, to Root Error Status Reg,
         * Root Error ID Reg, and Root error producer/consumer index.
         */
-       rpc->e_lock = SPIN_LOCK_UNLOCKED;
+       spin_lock_init(&rpc->e_lock);
 
        rpc->rpd = dev;
        INIT_WORK(&rpc->dpc_handler, aer_isr);
index 5cca394d59993b14cdd2549781ea4aafe70648cc..c7ad68b6c6d661873daa729c9609326d47e7dbea 100644 (file)
 #define AER_ERROR_MASK                 0x001fffff
 #define AER_ERROR(d)                   (d & AER_ERROR_MASK)
 
-#define OSC_METHOD_RUN_SUCCESS         0
-#define OSC_METHOD_NOT_SUPPORTED       1
-#define OSC_METHOD_RUN_FAILURE         2
-
 /* Root Error Status Register Bits */
 #define ROOT_ERR_STATUS_MASKS                  0x0f
 
@@ -121,6 +117,14 @@ extern void aer_delete_rootport(struct aer_rpc *rpc);
 extern int aer_init(struct pcie_device *dev);
 extern void aer_isr(struct work_struct *work);
 extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
-extern int aer_osc_setup(struct pci_dev *dev);
+
+#ifdef CONFIG_ACPI
+extern int aer_osc_setup(struct pcie_device *pciedev);
+#else
+static inline int aer_osc_setup(struct pcie_device *pciedev)
+{
+       return 0;
+}
+#endif
 
 #endif //_AERDRV_H_
index fa68e89ebec962aa4b007172a52db992f442750b..1a1eb45a779e3862f8ef634cd425d4f117444661 100644 (file)
 
 /**
  * aer_osc_setup - run ACPI _OSC method
+ * @pciedev: pcie_device which AER is being enabled on
  *
- * Return:
- *     Zero if success. Nonzero for otherwise.
+ * @return: Zero on success. Nonzero otherwise.
  *
  * Invoked when PCIE bus loads AER service driver. To avoid conflict with
  * BIOS AER support requires BIOS to yield AER control to OS native driver.
  **/
-int aer_osc_setup(struct pci_dev *dev)
+int aer_osc_setup(struct pcie_device *pciedev)
 {
-       int retval = OSC_METHOD_RUN_SUCCESS;
-       acpi_status status;
-       acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
-       struct pci_dev *pdev = dev;
+       acpi_status status = AE_NOT_FOUND;
+       struct pci_dev *pdev = pciedev->port;
+       acpi_handle handle = DEVICE_ACPI_HANDLE(&pdev->dev);
        struct pci_bus *parent;
 
        while (!handle) {
@@ -50,19 +49,20 @@ int aer_osc_setup(struct pci_dev *dev)
                pdev = parent->self;
        }
 
-       if (!handle)
-               return OSC_METHOD_NOT_SUPPORTED;
+       if (handle) {
+               pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
+               status = pci_osc_control_set(handle,
+                                       OSC_PCI_EXPRESS_AER_CONTROL |
+                                       OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+       }
 
-       pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
-       status = pci_osc_control_set(handle, OSC_PCI_EXPRESS_AER_CONTROL |
-               OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
        if (ACPI_FAILURE(status)) {
-               if (status == AE_SUPPORT)
-                       retval = OSC_METHOD_NOT_SUPPORTED;
-               else
-                       retval = OSC_METHOD_RUN_FAILURE;
+               printk(KERN_DEBUG "AER service couldn't init device %s - %s\n",
+                   pciedev->device.bus_id,
+                   (status == AE_SUPPORT || status == AE_NOT_FOUND) ?
+                   "no _OSC support" : "Run ACPI _OSC fails");
+               return -1;
        }
 
-       return retval;
+       return 0;
 }
-
index 08e13033ced8fc642df5565c1e9cf07867563862..92a8469b21bacecc2f161621553029ea99222d1e 100644 (file)
@@ -22,8 +22,6 @@
 #include <linux/errno.h>
 #include <linux/pm.h>
 #include <linux/suspend.h>
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
 #include <linux/delay.h>
 #include "aerdrv.h"
 
@@ -119,6 +117,21 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
        return 0;
 }
 
+int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
+{
+       int pos;
+       u32 status;
+
+       pos = pci_find_aer_capability(dev);
+       if (!pos)
+               return -EIO;
+
+       pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
+       pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status);
+
+       return 0;
+}
+
 static int find_device_iter(struct device *device, void *data)
 {
        struct pci_dev *dev;
@@ -733,20 +746,8 @@ void aer_delete_rootport(struct aer_rpc *rpc)
  **/
 int aer_init(struct pcie_device *dev)
 {
-       int status;
-
-       /* Run _OSC Method */
-       status = aer_osc_setup(dev->port);
-
-       if(status != OSC_METHOD_RUN_SUCCESS) {
-               printk(KERN_DEBUG "%s: AER service init fails - %s\n",
-               __FUNCTION__,
-               (status == OSC_METHOD_NOT_SUPPORTED) ?
-                       "No ACPI _OSC support" : "Run ACPI _OSC fails");
-
-               if (!forceload)
-                       return status;
-       }
+       if (aer_osc_setup(dev) && !forceload)
+               return -ENXIO;
 
        return AER_SUCCESS;
 }
@@ -755,4 +756,5 @@ EXPORT_SYMBOL_GPL(pci_find_aer_capability);
 EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
 EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
 EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
+EXPORT_SYMBOL_GPL(pci_cleanup_aer_correct_error_status);
 
index e48fcf0896212193ace241d8f066fb8de9100feb..a7bce75c673281641bec37054c10d3def7afabe5 100644 (file)
@@ -39,7 +39,6 @@ static void pci_create_legacy_files(struct pci_bus *b)
                b->legacy_io->attr.name = "legacy_io";
                b->legacy_io->size = 0xffff;
                b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
-               b->legacy_io->attr.owner = THIS_MODULE;
                b->legacy_io->read = pci_read_legacy_io;
                b->legacy_io->write = pci_write_legacy_io;
                class_device_create_bin_file(&b->class_dev, b->legacy_io);
@@ -49,7 +48,6 @@ static void pci_create_legacy_files(struct pci_bus *b)
                b->legacy_mem->attr.name = "legacy_mem";
                b->legacy_mem->size = 1024*1024;
                b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
-               b->legacy_mem->attr.owner = THIS_MODULE;
                b->legacy_mem->mmap = pci_mmap_legacy_mem;
                class_device_create_bin_file(&b->class_dev, b->legacy_mem);
        }
@@ -656,7 +654,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
                               pcibios_assign_all_busses() ? " " :
                               " (try 'pci=assign-busses')");
                        printk(KERN_WARNING "Please report the result to "
-                              "linux-kernel to fix this permanently\n");
+                              "<bk@suse.de> to fix this permanently\n");
                }
                bus = bus->parent;
        }
@@ -702,6 +700,7 @@ static int pci_setup_device(struct pci_dev * dev)
                dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
 
        pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
+       dev->revision = class & 0xff;
        class >>= 8;                                /* upper 3 bytes */
        dev->class = class;
        class >>= 8;
index 0425a7b7350d987760bfff76cbd0e0af6d311800..cfa0dfe61b1af384b89da6147cb75bf93d6dc70d 100644 (file)
@@ -480,7 +480,6 @@ static int __init pci_proc_init(void)
 __initcall(pci_proc_init);
 
 #ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pci_proc_attach_device);
 EXPORT_SYMBOL(pci_proc_detach_bus);
 #endif
 
index 01d8f8a8843c5c064250f09af7396a1e3aa7cdd0..c559085c89a50f2c0ee909191c2ef0b0ea549f66 100644 (file)
@@ -587,10 +587,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,        PCI_DEVICE_ID_VIA_8237,         quirk_via_v
  */
 static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
 {
-       u8 rev;
-
-       pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-       if (rev >= 0x02) {
+       if (dev->revision >= 0x02) {
                printk(KERN_WARNING "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
                printk(KERN_WARNING "        : booting with the \"noapic\" option.\n");
        }
@@ -610,13 +607,12 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID,                     quirk_ioapic_rmw );
 #define AMD8131_NIOAMODE_BIT 0
 static void quirk_amd_8131_ioapic(struct pci_dev *dev)
 { 
-        unsigned char revid, tmp;
+        unsigned char tmp;
         
         if (nr_ioapics == 0) 
                 return;
 
-        pci_read_config_byte(dev, PCI_REVISION_ID, &revid);
-        if (revid == AMD8131_revA0 || revid == AMD8131_revB0) {
+        if (dev->revision == AMD8131_revA0 || dev->revision == AMD8131_revB0) {
                 printk(KERN_INFO "Fixing up AMD8131 IOAPIC mode\n"); 
                 pci_read_config_byte( dev, AMD8131_MISC, &tmp);
                 tmp &= ~(1 << AMD8131_NIOAMODE_BIT);
@@ -627,6 +623,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_
 DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
 #endif /* CONFIG_X86_IO_APIC */
 
+/*
+ * Some settings of MMRBC can lead to data corruption so block changes.
+ * See AMD 8131 HyperTransport PCI-X Tunnel Revision Guide
+ */
+static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev)
+{
+       unsigned char revid;
+
+       pci_read_config_byte(dev, PCI_REVISION_ID, &revid);
+       if (dev->subordinate && revid <= 0x12) {
+               printk(KERN_INFO "AMD8131 rev %x detected, disabling PCI-X "
+                               "MMRBC\n", revid);
+               dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MMRBC;
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_mmrbc);
 
 /*
  * FIXME: it is questionable that quirk_via_acpi
@@ -843,10 +855,8 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX,      PCI_DEVICE_ID_CYRIX_PCI_MASTER, qu
 static void quirk_disable_pxb(struct pci_dev *pdev)
 {
        u16 config;
-       u8 rev;
        
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-       if (rev != 0x04)                /* Only C0 requires this */
+       if (pdev->revision != 0x04)             /* Only C0 requires this */
                return;
        pci_read_config_word(pdev, 0x40, &config);
        if (config & (1<<6)) {
index d087e0817715a71a9405415d24f47220552c3533..dbbcc04abd1af1fe06eafc7be1a647d847233e25 100644 (file)
@@ -53,6 +53,49 @@ static void pci_disable_rom(struct pci_dev *pdev)
        pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
 }
 
+/**
+ * pci_get_rom_size - obtain the actual size of the ROM image
+ * @rom: kernel virtual pointer to image of ROM
+ * @size: size of PCI window
+ *  return: size of actual ROM image
+ *
+ * Determine the actual length of the ROM image.
+ * The PCI window size could be much larger than the
+ * actual image size.
+ */
+size_t pci_get_rom_size(void __iomem *rom, size_t size)
+{
+       void __iomem *image;
+       int last_image;
+
+       image = rom;
+       do {
+               void __iomem *pds;
+               /* Standard PCI ROMs start out with these bytes 55 AA */
+               if (readb(image) != 0x55)
+                       break;
+               if (readb(image + 1) != 0xAA)
+                       break;
+               /* get the PCI data structure and check its signature */
+               pds = image + readw(image + 24);
+               if (readb(pds) != 'P')
+                       break;
+               if (readb(pds + 1) != 'C')
+                       break;
+               if (readb(pds + 2) != 'I')
+                       break;
+               if (readb(pds + 3) != 'R')
+                       break;
+               last_image = readb(pds + 21) & 0x80;
+               /* this length is reliable */
+               image += readw(pds + 16) * 512;
+       } while (!last_image);
+
+       /* never return a size larger than the PCI resource window */
+       /* there are known ROMs that get the size wrong */
+       return min((size_t)(image - rom), size);
+}
+
 /**
  * pci_map_rom - map a PCI ROM to kernel space
  * @pdev: pointer to pci device struct
@@ -68,8 +111,6 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
        struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
        loff_t start;
        void __iomem *rom;
-       void __iomem *image;
-       int last_image;
 
        /*
         * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
@@ -117,33 +158,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
         * size is much larger than the actual size of the ROM.
         * True size is important if the ROM is going to be copied.
         */
-       image = rom;
-       do {
-               void __iomem *pds;
-               /* Standard PCI ROMs start out with these bytes 55 AA */
-               if (readb(image) != 0x55)
-                       break;
-               if (readb(image + 1) != 0xAA)
-                       break;
-               /* get the PCI data structure and check its signature */
-               pds = image + readw(image + 24);
-               if (readb(pds) != 'P')
-                       break;
-               if (readb(pds + 1) != 'C')
-                       break;
-               if (readb(pds + 2) != 'I')
-                       break;
-               if (readb(pds + 3) != 'R')
-                       break;
-               last_image = readb(pds + 21) & 0x80;
-               /* this length is reliable */
-               image += readw(pds + 16) * 512;
-       } while (!last_image);
-
-       /* never return a size larger than the PCI resource window */
-       /* there are known ROMs that get the size wrong */
-       *size = min((size_t)(image - rom), *size);
-
+       *size = pci_get_rom_size(rom, *size);
        return rom;
 }
 
index c13232435dc06322f824b1f4fd07d34bdce112bb..9f7090fa8771401c954782eec3e052f5e29e7770 100644 (file)
@@ -139,12 +139,14 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
 }
 
 /**
- * pci_get_bus_and_slot - locate PCI device from a given PCI slot
+ * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot
  * @bus: number of PCI bus on which desired PCI device resides
  * @devfn: encodes number of PCI slot in which the desired PCI
  * device resides and the logical device number within that slot
  * in case of multi-function devices.
  *
+ * Note: the bus/slot search is limited to PCI domain (segment) 0.
+ *
  * Given a PCI bus and slot/function number, the desired PCI device
  * is located in system global list of PCI devices.  If the device
  * is found, a pointer to its data structure is returned.  If no
@@ -157,7 +159,8 @@ struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
        struct pci_dev *dev = NULL;
 
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               if (dev->bus->number == bus && dev->devfn == devfn)
+               if (pci_domain_nr(dev->bus) == 0 &&
+                  (dev->bus->number == bus && dev->devfn == devfn))
                        return dev;
        }
        return NULL;
index 5ec297d7a5b4c236219a1086c0db63db7d508f56..5e5191ec8de65931f916c4659e42cf1758e49409 100644 (file)
@@ -34,8 +34,6 @@
 #define DBG(x...)
 #endif
 
-#define ROUND_UP(x, a)         (((x) + (a) - 1) & ~((a) - 1))
-
 static void pbus_assign_resources_sorted(struct pci_bus *bus)
 {
        struct pci_dev *dev;
@@ -310,7 +308,7 @@ static void pbus_size_io(struct pci_bus *bus)
 #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
        size = (size & 0xff) + ((size & ~0xffUL) << 2);
 #endif
-       size = ROUND_UP(size + size1, 4096);
+       size = ALIGN(size + size1, 4096);
        if (!size) {
                b_res->flags = 0;
                return;
@@ -378,11 +376,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
 
                if (!align)
                        min_align = align1;
-               else if (ROUND_UP(align + min_align, min_align) < align1)
+               else if (ALIGN(align + min_align, min_align) < align1)
                        min_align = align1 >> 1;
                align += aligns[order];
        }
-       size = ROUND_UP(size, min_align);
+       size = ALIGN(size, min_align);
        if (!size) {
                b_res->flags = 0;
                return 1;
index 9d37fec27f24668d1ede8229439b82bb36561b61..2ac050d7f8cffbc12e57384ee96894917236c73e 100644 (file)
@@ -23,14 +23,14 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
        u8 byte;
        u16 word;
        u32 dword;
-       long err, cfg_ret;
+       long err;
+       long cfg_ret;
 
-       err = -EPERM;
        if (!capable(CAP_SYS_ADMIN))
-               goto error;
+               return -EPERM;
 
        err = -ENODEV;
-       dev = pci_find_slot(bus, dfn);
+       dev = pci_get_bus_and_slot(bus, dfn);
        if (!dev)
                goto error;
 
@@ -66,7 +66,8 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
        case 4:
                err = put_user(dword, (unsigned int __user *)buf);
                break;
-       };
+       }
+       pci_dev_put(dev);
        return err;
 
 error:
@@ -83,7 +84,8 @@ error:
        case 4:
                put_user(-1, (unsigned int __user *)buf);
                break;
-       };
+       }
+       pci_dev_put(dev);
        return err;
 }
 
@@ -101,7 +103,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       dev = pci_find_slot(bus, dfn);
+       dev = pci_get_bus_and_slot(bus, dfn);
        if (!dev)
                return -ENODEV;
 
@@ -137,8 +139,8 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
        default:
                err = -EINVAL;
                break;
-       };
+       }
        unlock_kernel();
-
+       pci_dev_put(dev);
        return err;
 }
index a2bb46526b56cdd8028a49e1394034d501a40807..b4409002b7f8415a88c4a8a823dbcd0ffa96f530 100644 (file)
@@ -283,7 +283,9 @@ static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off
        return (ret);
 }
 
-static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t pccard_show_cis(struct kobject *kobj,
+                              struct bin_attribute *bin_attr,
+                              char *buf, loff_t off, size_t count)
 {
        unsigned int size = 0x200;
 
@@ -311,7 +313,9 @@ static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size
        return (count);
 }
 
-static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t pccard_store_cis(struct kobject *kobj,
+                               struct bin_attribute *bin_attr,
+                               char *buf, loff_t off, size_t count)
 {
        struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
        cisdump_t *cis;
@@ -366,7 +370,7 @@ static struct device_attribute *pccard_socket_attributes[] = {
 };
 
 static struct bin_attribute pccard_cis_attr = {
-       .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE},
+       .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR },
        .size = 0x200,
        .read = pccard_show_cis,
        .write = pccard_store_cis,
index eed91434417d7d39e86a2bca4602700e8dfe3177..659e31164cf08b3c94cb6b6d09821f79e9f97793 100644 (file)
@@ -67,7 +67,8 @@ struct device_attribute rio_dev_attrs[] = {
 };
 
 static ssize_t
-rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+rio_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+               char *buf, loff_t off, size_t count)
 {
        struct rio_dev *dev =
            to_rio_dev(container_of(kobj, struct device, kobj));
@@ -137,7 +138,8 @@ rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
 }
 
 static ssize_t
-rio_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+rio_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+                char *buf, loff_t off, size_t count)
 {
        struct rio_dev *dev =
            to_rio_dev(container_of(kobj, struct device, kobj));
@@ -197,7 +199,6 @@ static struct bin_attribute rio_config_attr = {
        .attr = {
                 .name = "config",
                 .mode = S_IRUGO | S_IWUSR,
-                .owner = THIS_MODULE,
                 },
        .size = 0x200000,
        .read = rio_read_config,
index afa64c7fa2e2d67152b50fe75b011e7cf2c8a6f2..f98a83a11aaeb66411a9083f78f887807528e732 100644 (file)
@@ -258,8 +258,9 @@ static const struct rtc_class_ops ds1553_rtc_ops = {
        .ioctl          = ds1553_rtc_ioctl,
 };
 
-static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
-                                loff_t pos, size_t size)
+static ssize_t ds1553_nvram_read(struct kobject *kobj,
+                                struct bin_attribute *bin_attr,
+                                char *buf, loff_t pos, size_t size)
 {
        struct platform_device *pdev =
                to_platform_device(container_of(kobj, struct device, kobj));
@@ -272,8 +273,9 @@ static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
        return count;
 }
 
-static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf,
-                                 loff_t pos, size_t size)
+static ssize_t ds1553_nvram_write(struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
+                                 char *buf, loff_t pos, size_t size)
 {
        struct platform_device *pdev =
                to_platform_device(container_of(kobj, struct device, kobj));
@@ -290,7 +292,6 @@ static struct bin_attribute ds1553_nvram_attr = {
        .attr = {
                .name = "nvram",
                .mode = S_IRUGO | S_IWUGO,
-               .owner = THIS_MODULE,
        },
        .size = RTC_OFFSET,
        .read = ds1553_nvram_read,
index d68288b389dc18b041c07060dac49da774da5df1..d1778ae8bca58c6e9b8a45dc534e4345b21cc7a8 100644 (file)
@@ -127,8 +127,9 @@ static const struct rtc_class_ops ds1742_rtc_ops = {
        .set_time       = ds1742_rtc_set_time,
 };
 
-static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
-                                loff_t pos, size_t size)
+static ssize_t ds1742_nvram_read(struct kobject *kobj,
+                                struct bin_attribute *bin_attr,
+                                char *buf, loff_t pos, size_t size)
 {
        struct platform_device *pdev =
                to_platform_device(container_of(kobj, struct device, kobj));
@@ -141,8 +142,9 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
        return count;
 }
 
-static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf,
-                                 loff_t pos, size_t size)
+static ssize_t ds1742_nvram_write(struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
+                                 char *buf, loff_t pos, size_t size)
 {
        struct platform_device *pdev =
                to_platform_device(container_of(kobj, struct device, kobj));
@@ -159,7 +161,6 @@ static struct bin_attribute ds1742_nvram_attr = {
        .attr = {
                .name = "nvram",
                .mode = S_IRUGO | S_IWUGO,
-               .owner = THIS_MODULE,
        },
        .read = ds1742_nvram_read,
        .write = ds1742_nvram_write,
index af7596ef29e2d837f2c9c8ea6b6d4fc7b7d37102..ce2f78de7a80b9ce2285ad7c8d4fffb02179855e 100644 (file)
  *  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/err.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/rtc.h>
 #include <asm/div64.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/vr41xx/irq.h>
 
 MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
 MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
 MODULE_LICENSE("GPL");
 
-#define RTC1_TYPE1_START       0x0b0000c0UL
-#define RTC1_TYPE1_END         0x0b0000dfUL
-#define RTC2_TYPE1_START       0x0b0001c0UL
-#define RTC2_TYPE1_END         0x0b0001dfUL
-
-#define RTC1_TYPE2_START       0x0f000100UL
-#define RTC1_TYPE2_END         0x0f00011fUL
-#define RTC2_TYPE2_START       0x0f000120UL
-#define RTC2_TYPE2_END         0x0f00013fUL
-
-#define RTC1_SIZE              0x20
-#define RTC2_SIZE              0x20
-
 /* RTC 1 registers */
 #define ETIMELREG              0x00
 #define ETIMEMREG              0x02
@@ -98,13 +85,8 @@ static char rtc_name[] = "RTC";
 static unsigned long periodic_frequency;
 static unsigned long periodic_count;
 static unsigned int alarm_enabled;
-
-struct resource rtc_resource[2] = {
-       {       .name   = rtc_name,
-               .flags  = IORESOURCE_MEM,       },
-       {       .name   = rtc_name,
-               .flags  = IORESOURCE_MEM,       },
-};
+static int aie_irq = -1;
+static int pie_irq = -1;
 
 static inline unsigned long read_elapsed_second(void)
 {
@@ -150,8 +132,8 @@ static void vr41xx_rtc_release(struct device *dev)
 
        spin_unlock_irq(&rtc_lock);
 
-       disable_irq(ELAPSEDTIME_IRQ);
-       disable_irq(RTCLONG1_IRQ);
+       disable_irq(aie_irq);
+       disable_irq(pie_irq);
 }
 
 static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
@@ -209,14 +191,14 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
        spin_lock_irq(&rtc_lock);
 
        if (alarm_enabled)
-               disable_irq(ELAPSEDTIME_IRQ);
+               disable_irq(aie_irq);
 
        rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
        rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
        rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
 
        if (wkalrm->enabled)
-               enable_irq(ELAPSEDTIME_IRQ);
+               enable_irq(aie_irq);
 
        alarm_enabled = wkalrm->enabled;
 
@@ -234,7 +216,7 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
                spin_lock_irq(&rtc_lock);
 
                if (!alarm_enabled) {
-                       enable_irq(ELAPSEDTIME_IRQ);
+                       enable_irq(aie_irq);
                        alarm_enabled = 1;
                }
 
@@ -244,17 +226,17 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
                spin_lock_irq(&rtc_lock);
 
                if (alarm_enabled) {
-                       disable_irq(ELAPSEDTIME_IRQ);
+                       disable_irq(aie_irq);
                        alarm_enabled = 0;
                }
 
                spin_unlock_irq(&rtc_lock);
                break;
        case RTC_PIE_ON:
-               enable_irq(RTCLONG1_IRQ);
+               enable_irq(pie_irq);
                break;
        case RTC_PIE_OFF:
-               disable_irq(RTCLONG1_IRQ);
+               disable_irq(pie_irq);
                break;
        case RTC_IRQP_READ:
                return put_user(periodic_frequency, (unsigned long __user *)arg);
@@ -331,31 +313,37 @@ static const struct rtc_class_ops vr41xx_rtc_ops = {
 
 static int __devinit rtc_probe(struct platform_device *pdev)
 {
+       struct resource *res;
        struct rtc_device *rtc;
-       unsigned int irq;
        int retval;
 
-       if (pdev->num_resources != 2)
+       if (pdev->num_resources != 4)
                return -EBUSY;
 
-       rtc1_base = ioremap(pdev->resource[0].start, RTC1_SIZE);
-       if (rtc1_base == NULL)
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
                return -EBUSY;
 
-       rtc2_base = ioremap(pdev->resource[1].start, RTC2_SIZE);
-       if (rtc2_base == NULL) {
-               iounmap(rtc1_base);
-               rtc1_base = NULL;
+       rtc1_base = ioremap(res->start, res->end - res->start + 1);
+       if (!rtc1_base)
                return -EBUSY;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!res) {
+               retval = -EBUSY;
+               goto err_rtc1_iounmap;
+       }
+
+       rtc2_base = ioremap(res->start, res->end - res->start + 1);
+       if (!rtc2_base) {
+               retval = -EBUSY;
+               goto err_rtc1_iounmap;
        }
 
        rtc = rtc_device_register(rtc_name, &pdev->dev, &vr41xx_rtc_ops, THIS_MODULE);
        if (IS_ERR(rtc)) {
-               iounmap(rtc1_base);
-               iounmap(rtc2_base);
-               rtc1_base = NULL;
-               rtc2_base = NULL;
-               return PTR_ERR(rtc);
+               retval = PTR_ERR(rtc);
+               goto err_iounmap_all;
        }
 
        spin_lock_irq(&rtc_lock);
@@ -368,35 +356,50 @@ static int __devinit rtc_probe(struct platform_device *pdev)
 
        spin_unlock_irq(&rtc_lock);
 
-       irq = ELAPSEDTIME_IRQ;
-       retval = request_irq(irq, elapsedtime_interrupt, IRQF_DISABLED,
-                            "elapsed_time", pdev);
-       if (retval == 0) {
-               irq = RTCLONG1_IRQ;
-               retval = request_irq(irq, rtclong1_interrupt, IRQF_DISABLED,
-                                    "rtclong1", pdev);
+       aie_irq = platform_get_irq(pdev, 0);
+       if (aie_irq < 0 || aie_irq >= NR_IRQS) {
+               retval = -EBUSY;
+               goto err_device_unregister;
        }
 
-       if (retval < 0) {
-               printk(KERN_ERR "rtc: IRQ%d is busy\n", irq);
-               rtc_device_unregister(rtc);
-               if (irq == RTCLONG1_IRQ)
-                       free_irq(ELAPSEDTIME_IRQ, NULL);
-               iounmap(rtc1_base);
-               iounmap(rtc2_base);
-               rtc1_base = NULL;
-               rtc2_base = NULL;
-               return retval;
-       }
+       retval = request_irq(aie_irq, elapsedtime_interrupt, IRQF_DISABLED,
+                            "elapsed_time", pdev);
+       if (retval < 0)
+               goto err_device_unregister;
+
+       pie_irq = platform_get_irq(pdev, 1);
+       if (pie_irq < 0 || pie_irq >= NR_IRQS)
+               goto err_free_irq;
+
+       retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED,
+                            "rtclong1", pdev);
+       if (retval < 0)
+               goto err_free_irq;
 
        platform_set_drvdata(pdev, rtc);
 
-       disable_irq(ELAPSEDTIME_IRQ);
-       disable_irq(RTCLONG1_IRQ);
+       disable_irq(aie_irq);
+       disable_irq(pie_irq);
 
        printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n");
 
        return 0;
+
+err_free_irq:
+       free_irq(aie_irq, pdev);
+
+err_device_unregister:
+       rtc_device_unregister(rtc);
+
+err_iounmap_all:
+       iounmap(rtc2_base);
+       rtc2_base = NULL;
+
+err_rtc1_iounmap:
+       iounmap(rtc1_base);
+       rtc1_base = NULL;
+
+       return retval;
 }
 
 static int __devexit rtc_remove(struct platform_device *pdev)
@@ -404,23 +407,21 @@ static int __devexit rtc_remove(struct platform_device *pdev)
        struct rtc_device *rtc;
 
        rtc = platform_get_drvdata(pdev);
-       if (rtc != NULL)
+       if (rtc)
                rtc_device_unregister(rtc);
 
        platform_set_drvdata(pdev, NULL);
 
-       free_irq(ELAPSEDTIME_IRQ, NULL);
-       free_irq(RTCLONG1_IRQ, NULL);
-       if (rtc1_base != NULL)
+       free_irq(aie_irq, pdev);
+       free_irq(pie_irq, pdev);
+       if (rtc1_base)
                iounmap(rtc1_base);
-       if (rtc2_base != NULL)
+       if (rtc2_base)
                iounmap(rtc2_base);
 
        return 0;
 }
 
-static struct platform_device *rtc_platform_device;
-
 static struct platform_driver rtc_platform_driver = {
        .probe          = rtc_probe,
        .remove         = __devexit_p(rtc_remove),
@@ -432,55 +433,12 @@ static struct platform_driver rtc_platform_driver = {
 
 static int __init vr41xx_rtc_init(void)
 {
-       int retval;
-
-       switch (current_cpu_data.cputype) {
-       case CPU_VR4111:
-       case CPU_VR4121:
-               rtc_resource[0].start = RTC1_TYPE1_START;
-               rtc_resource[0].end = RTC1_TYPE1_END;
-               rtc_resource[1].start = RTC2_TYPE1_START;
-               rtc_resource[1].end = RTC2_TYPE1_END;
-               break;
-       case CPU_VR4122:
-       case CPU_VR4131:
-       case CPU_VR4133:
-               rtc_resource[0].start = RTC1_TYPE2_START;
-               rtc_resource[0].end = RTC1_TYPE2_END;
-               rtc_resource[1].start = RTC2_TYPE2_START;
-               rtc_resource[1].end = RTC2_TYPE2_END;
-               break;
-       default:
-               return -ENODEV;
-               break;
-       }
-
-       rtc_platform_device = platform_device_alloc("RTC", -1);
-       if (rtc_platform_device == NULL)
-               return -ENOMEM;
-
-       retval = platform_device_add_resources(rtc_platform_device,
-                               rtc_resource, ARRAY_SIZE(rtc_resource));
-
-       if (retval == 0)
-               retval = platform_device_add(rtc_platform_device);
-
-       if (retval < 0) {
-               platform_device_put(rtc_platform_device);
-               return retval;
-       }
-
-       retval = platform_driver_register(&rtc_platform_driver);
-       if (retval < 0)
-               platform_device_unregister(rtc_platform_device);
-
-       return retval;
+       return platform_driver_register(&rtc_platform_driver);
 }
 
 static void __exit vr41xx_rtc_exit(void)
 {
        platform_driver_unregister(&rtc_platform_driver);
-       platform_device_unregister(rtc_platform_device);
 }
 
 module_init(vr41xx_rtc_init);
index 513d1a611aaba46edb1343ae0bb2ceab58683680..b3fae357ca494e52ac257e80b3eb223417811de7 100644 (file)
@@ -9,6 +9,9 @@
  *
  * based on a lot of other RTC drivers.
  *
+ * Information and datasheet:
+ * http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html
+ *
  * 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.
@@ -26,7 +29,7 @@
  * Two bytes need to be written to read a single register,
  * while most other chips just require one and take the second
  * one as the data to be written. To prevent corrupting
- * unknown chips, the user must explicitely set the probe parameter.
+ * unknown chips, the user must explicitly set the probe parameter.
  */
 
 static unsigned short normal_i2c[] = { I2C_CLIENT_END };
index ac289e6eadfe9ea1ef0a54c7d0de74b68c243108..b57d93d986c0fa9fc6bf6a8cf4923542899207e5 100644 (file)
@@ -141,8 +141,9 @@ static int s390_vary_chpid(struct chp_id chpid, int on)
 /*
  * Channel measurement related functions
  */
-static ssize_t chp_measurement_chars_read(struct kobject *kobj, char *buf,
-                                         loff_t off, size_t count)
+static ssize_t chp_measurement_chars_read(struct kobject *kobj,
+                                         struct bin_attribute *bin_attr,
+                                         char *buf, loff_t off, size_t count)
 {
        struct channel_path *chp;
        unsigned int size;
@@ -165,7 +166,6 @@ static struct bin_attribute chp_measurement_chars_attr = {
        .attr = {
                .name = "measurement_chars",
                .mode = S_IRUSR,
-               .owner = THIS_MODULE,
        },
        .size = sizeof(struct cmg_chars),
        .read = chp_measurement_chars_read,
@@ -193,8 +193,9 @@ static void chp_measurement_copy_block(struct cmg_entry *buf,
        } while (reference_buf.values[0] != buf->values[0]);
 }
 
-static ssize_t chp_measurement_read(struct kobject *kobj, char *buf,
-                                   loff_t off, size_t count)
+static ssize_t chp_measurement_read(struct kobject *kobj,
+                                   struct bin_attribute *bin_attr,
+                                   char *buf, loff_t off, size_t count)
 {
        struct channel_path *chp;
        struct channel_subsystem *css;
@@ -217,7 +218,6 @@ static struct bin_attribute chp_measurement_attr = {
        .attr = {
                .name = "measurement",
                .mode = S_IRUSR,
-               .owner = THIS_MODULE,
        },
        .size = sizeof(struct cmg_entry),
        .read = chp_measurement_read,
index 65ffc21afc37525d53010daff7d0ccf86d9a3bb5..bb0287ad1aacff26f97cd80ecf6278ad946f003b 100644 (file)
@@ -991,7 +991,7 @@ static struct attribute_group qeth_osn_device_attr_group = {
 
 #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store)                      \
 struct device_attribute dev_attr_##_id = {                                  \
-       .attr = {.name=__stringify(_name), .mode=_mode, .owner=THIS_MODULE },\
+       .attr = {.name=__stringify(_name), .mode=_mode, },\
        .show   = _show,                                                     \
        .store  = _store,                                                    \
 };
index 27852b43b9044a829ffc2d3c4bc3ff5fe09885a4..1c0d7578e791e8fbeaeaa147dc54360cc85e1c1a 100644 (file)
@@ -223,13 +223,8 @@ static int __devinit asd_common_setup(struct asd_ha_struct *asd_ha)
 {
        int err, i;
 
-       err = pci_read_config_byte(asd_ha->pcidev, PCI_REVISION_ID,
-                                  &asd_ha->revision_id);
-       if (err) {
-               asd_printk("couldn't read REVISION ID register of %s\n",
-                          pci_name(asd_ha->pcidev));
-               goto Err;
-       }
+       asd_ha->revision_id = asd_ha->pcidev->revision;
+
        err = -ENODEV;
        if (asd_ha->revision_id < AIC9410_DEV_REV_B0) {
                asd_printk("%s is revision %s (%X), which is not supported\n",
index 03bfed61bffcb0da68f8e94b51ccac757ef0673d..06c0dce3b83916095064eab9af2c440098a9bea3 100644 (file)
@@ -59,8 +59,9 @@
 struct class_device_attribute *arcmsr_host_attrs[];
 
 static ssize_t
-arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+arcmsr_sysfs_iop_message_read(struct kobject *kobj,
+                             struct bin_attribute *bin_attr,
+                             char *buf, loff_t off, size_t count)
 {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *host = class_to_shost(cdev);
@@ -105,8 +106,9 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off,
 }
 
 static ssize_t
-arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+arcmsr_sysfs_iop_message_write(struct kobject *kobj,
+                              struct bin_attribute *bin_attr,
+                              char *buf, loff_t off, size_t count)
 {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *host = class_to_shost(cdev);
@@ -152,8 +154,9 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off,
 }
 
 static ssize_t
-arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
+                              struct bin_attribute *bin_attr,
+                              char *buf, loff_t off, size_t count)
 {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *host = class_to_shost(cdev);
@@ -188,7 +191,6 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = {
        .attr = {
                .name = "mu_read",
                .mode = S_IRUSR ,
-               .owner = THIS_MODULE,
        },
        .size = 1032,
        .read = arcmsr_sysfs_iop_message_read,
@@ -198,7 +200,6 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = {
        .attr = {
                .name = "mu_write",
                .mode = S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = 1032,
        .write = arcmsr_sysfs_iop_message_write,
@@ -208,7 +209,6 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
        .attr = {
                .name = "mu_clear",
                .mode = S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = 1,
        .write = arcmsr_sysfs_iop_message_clear,
index fa6ff295e5683b544ceea30250de287fbdb362d6..b3bf77f1ec050e62785067b9d38826ccb52948d4 100644 (file)
@@ -2465,6 +2465,7 @@ restart:
 /**
  * ipr_read_trace - Dump the adapter trace
  * @kobj:              kobject struct
+ * @bin_attr:          bin_attribute struct
  * @buf:               buffer
  * @off:               offset
  * @count:             buffer size
@@ -2472,8 +2473,9 @@ restart:
  * Return value:
  *     number of bytes printed to buffer
  **/
-static ssize_t ipr_read_trace(struct kobject *kobj, char *buf,
-                             loff_t off, size_t count)
+static ssize_t ipr_read_trace(struct kobject *kobj,
+                             struct bin_attribute *bin_attr,
+                             char *buf, loff_t off, size_t count)
 {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *shost = class_to_shost(cdev);
@@ -3166,6 +3168,7 @@ static struct class_device_attribute *ipr_ioa_attrs[] = {
 /**
  * ipr_read_dump - Dump the adapter
  * @kobj:              kobject struct
+ * @bin_attr:          bin_attribute struct
  * @buf:               buffer
  * @off:               offset
  * @count:             buffer size
@@ -3173,8 +3176,9 @@ static struct class_device_attribute *ipr_ioa_attrs[] = {
  * Return value:
  *     number of bytes printed to buffer
  **/
-static ssize_t ipr_read_dump(struct kobject *kobj, char *buf,
-                             loff_t off, size_t count)
+static ssize_t ipr_read_dump(struct kobject *kobj,
+                            struct bin_attribute *bin_attr,
+                            char *buf, loff_t off, size_t count)
 {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *shost = class_to_shost(cdev);
@@ -3327,6 +3331,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg)
 /**
  * ipr_write_dump - Setup dump state of adapter
  * @kobj:              kobject struct
+ * @bin_attr:          bin_attribute struct
  * @buf:               buffer
  * @off:               offset
  * @count:             buffer size
@@ -3334,8 +3339,9 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg)
  * Return value:
  *     number of bytes printed to buffer
  **/
-static ssize_t ipr_write_dump(struct kobject *kobj, char *buf,
-                             loff_t off, size_t count)
+static ssize_t ipr_write_dump(struct kobject *kobj,
+                             struct bin_attribute *bin_attr,
+                             char *buf, loff_t off, size_t count)
 {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *shost = class_to_shost(cdev);
@@ -5367,18 +5373,12 @@ static const u16 ipr_blocked_processors[] = {
  **/
 static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg)
 {
-       u8 rev_id;
        int i;
 
-       if (ioa_cfg->type == 0x5702) {
-               if (pci_read_config_byte(ioa_cfg->pdev, PCI_REVISION_ID,
-                                        &rev_id) == PCIBIOS_SUCCESSFUL) {
-                       if (rev_id < 4) {
-                               for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++){
-                                       if (__is_processor(ipr_blocked_processors[i]))
-                                               return 1;
-                               }
-                       }
+       if ((ioa_cfg->type == 0x5702) && (ioa_cfg->pdev->revision < 4)) {
+               for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++){
+                       if (__is_processor(ipr_blocked_processors[i]))
+                               return 1;
                }
        }
        return 0;
@@ -7535,13 +7535,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        else
                ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT;
 
-       rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &ioa_cfg->revid);
-
-       if (rc != PCIBIOS_SUCCESSFUL) {
-               dev_err(&pdev->dev, "Failed to read PCI revision ID\n");
-               rc = -EIO;
-               goto out_scsi_host_put;
-       }
+       ioa_cfg->revid = pdev->revision;
 
        ipr_regs_pci = pci_resource_start(pdev, 0);
 
index 8b704f73055a43d075762bb1f1e4dd84fbd39b2a..40f148e0833f485034e1f30f5a93756f05abb42c 100644 (file)
@@ -7148,7 +7148,6 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
        uint32_t mem_addr;
        uint32_t io_len;
        uint32_t mem_len;
-       uint8_t revision_id;
        uint8_t bus;
        uint8_t func;
        uint8_t irq;
@@ -7227,12 +7226,6 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
                }
        }
 
-       /* get the revision ID */
-       if (pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id)) {
-               IPS_PRINTK(KERN_WARNING, pci_dev, "Can't get revision id.\n");
-               return -1;
-       }
-
        subdevice_id = pci_dev->subsystem_device;
 
        /* found a controller */
@@ -7258,7 +7251,7 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
        ha->mem_ptr = mem_ptr;
        ha->ioremap_ptr = ioremap_ptr;
        ha->host_num = (uint32_t) index;
-       ha->revision_id = revision_id;
+       ha->revision_id = pci_dev->revision;
        ha->slot_num = PCI_SLOT(pci_dev->devfn);
        ha->device_id = pci_dev->device;
        ha->subdevice_id = subdevice_id;
index e34442e405e8a8aa96e05f0f195b20958a9a2ddb..23e90c5f8f352be326ad3b9f6ec351cac7955ad0 100644 (file)
@@ -38,8 +38,10 @@ static int sas_disable_routing(struct domain_device *dev,  u8 *sas_addr);
 
 #if 0
 /* FIXME: smp needs to migrate into the sas class */
-static ssize_t smp_portal_read(struct kobject *, char *, loff_t, size_t);
-static ssize_t smp_portal_write(struct kobject *, char *, loff_t, size_t);
+static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *,
+                              char *, loff_t, size_t);
+static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *,
+                               char *, loff_t, size_t);
 #endif
 
 /* ---------- SMP task management ---------- */
@@ -1368,7 +1370,6 @@ static void sas_ex_smp_hook(struct domain_device *dev)
        memset(bin_attr, 0, sizeof(*bin_attr));
 
        bin_attr->attr.name = SMP_BIN_ATTR_NAME;
-       bin_attr->attr.owner = THIS_MODULE;
        bin_attr->attr.mode = 0600;
 
        bin_attr->size = 0;
@@ -1846,8 +1847,9 @@ out:
 #if 0
 /* ---------- SMP portal ---------- */
 
-static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs,
-                               size_t size)
+static ssize_t smp_portal_write(struct kobject *kobj,
+                               struct bin_attribute *bin_attr,
+                               char *buf, loff_t offs, size_t size)
 {
        struct domain_device *dev = to_dom_device(kobj);
        struct expander_device *ex = &dev->ex_dev;
@@ -1873,8 +1875,9 @@ static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs,
        return size;
 }
 
-static ssize_t smp_portal_read(struct kobject *kobj, char *buf, loff_t offs,
-                              size_t size)
+static ssize_t smp_portal_read(struct kobject *kobj,
+                              struct bin_attribute *bin_attr,
+                              char *buf, loff_t offs, size_t size)
 {
        struct domain_device *dev = to_dom_device(kobj);
        struct expander_device *ex = &dev->ex_dev;
index 95fe77e816f80a756b937f6012b8ab989e14ac74..5dfda9778c80b009b03ca242d23c0d9614099631 100644 (file)
@@ -1133,7 +1133,8 @@ struct class_device_attribute *lpfc_host_attrs[] = {
 };
 
 static ssize_t
-sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+                  char *buf, loff_t off, size_t count)
 {
        size_t buf_off;
        struct Scsi_Host *host = class_to_shost(container_of(kobj,
@@ -1165,7 +1166,8 @@ sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
 }
 
 static ssize_t
-sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+                 char *buf, loff_t off, size_t count)
 {
        size_t buf_off;
        uint32_t * tmp_ptr;
@@ -1200,7 +1202,6 @@ static struct bin_attribute sysfs_ctlreg_attr = {
        .attr = {
                .name = "ctlreg",
                .mode = S_IRUSR | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = 256,
        .read = sysfs_ctlreg_read,
@@ -1222,7 +1223,8 @@ sysfs_mbox_idle (struct lpfc_hba * phba)
 }
 
 static ssize_t
-sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+                char *buf, loff_t off, size_t count)
 {
        struct Scsi_Host * host =
                class_to_shost(container_of(kobj, struct class_device, kobj));
@@ -1274,7 +1276,8 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
 }
 
 static ssize_t
-sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+               char *buf, loff_t off, size_t count)
 {
        struct Scsi_Host *host =
                class_to_shost(container_of(kobj, struct class_device,
@@ -1422,7 +1425,6 @@ static struct bin_attribute sysfs_mbox_attr = {
        .attr = {
                .name = "mbox",
                .mode = S_IRUSR | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = MAILBOX_CMD_SIZE,
        .read = sysfs_mbox_read,
index dcb4ba0ecee1825067b2344562ab0e21d4df0601..955b2e48d04192579615d6030311e43688b2aae9 100644 (file)
@@ -1578,10 +1578,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        INIT_LIST_HEAD(&phba->fc_nodes);
 
        pci_set_master(pdev);
-       retval = pci_set_mwi(pdev);
-       if (retval)
-               dev_printk(KERN_WARNING, &pdev->dev,
-                          "Warning: pci_set_mwi returned %d\n", retval);
+       pci_try_set_mwi(pdev);
 
        if (pci_set_dma_mask(phba->pcidev, DMA_64BIT_MASK) != 0)
                if (pci_set_dma_mask(phba->pcidev, DMA_32BIT_MASK) != 0)
index f6f561d26bf0c9c317d133e9ee9110444856eb6a..3e9765f0281d948669347b1ef6e309ce36122adb 100644 (file)
@@ -3487,15 +3487,6 @@ static int nsp32_resume(struct pci_dev *pdev)
        return 0;
 }
 
-/* Enable wake event */
-static int nsp32_enable_wake(struct pci_dev *pdev, pci_power_t state, int enable)
-{
-       struct Scsi_Host *host = pci_get_drvdata(pdev);
-
-       nsp32_msg(KERN_INFO, "pci-enable_wake: stub, pdev=0x%p, enable=%d, slot=%s, host=0x%p", pdev, enable, pci_name(pdev), host);
-
-       return 0;
-}
 #endif
 
 /************************************************************************
@@ -3571,7 +3562,6 @@ static struct pci_driver nsp32_driver = {
 #ifdef CONFIG_PM
        .suspend        = nsp32_suspend, 
        .resume         = nsp32_resume, 
-       .enable_wake    = nsp32_enable_wake,
 #endif
 };
 
index 8081b637d97e06550253eb0ddb12bfba0ef27ba5..942db9de785efb274ff10aa311e93d994e1fd885 100644 (file)
@@ -11,8 +11,9 @@
 /* SYSFS attributes --------------------------------------------------------- */
 
 static ssize_t
-qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
+                          struct bin_attribute *bin_attr,
+                          char *buf, loff_t off, size_t count)
 {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@ -31,8 +32,9 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
 }
 
 static ssize_t
-qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
+                           struct bin_attribute *bin_attr,
+                           char *buf, loff_t off, size_t count)
 {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@ -73,7 +75,6 @@ static struct bin_attribute sysfs_fw_dump_attr = {
        .attr = {
                .name = "fw_dump",
                .mode = S_IRUSR | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = 0,
        .read = qla2x00_sysfs_read_fw_dump,
@@ -81,8 +82,9 @@ static struct bin_attribute sysfs_fw_dump_attr = {
 };
 
 static ssize_t
-qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_read_nvram(struct kobject *kobj,
+                        struct bin_attribute *bin_attr,
+                        char *buf, loff_t off, size_t count)
 {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@ -101,8 +103,9 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
 }
 
 static ssize_t
-qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_write_nvram(struct kobject *kobj,
+                         struct bin_attribute *bin_attr,
+                         char *buf, loff_t off, size_t count)
 {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@ -149,7 +152,6 @@ static struct bin_attribute sysfs_nvram_attr = {
        .attr = {
                .name = "nvram",
                .mode = S_IRUSR | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = 512,
        .read = qla2x00_sysfs_read_nvram,
@@ -157,8 +159,9 @@ static struct bin_attribute sysfs_nvram_attr = {
 };
 
 static ssize_t
-qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_read_optrom(struct kobject *kobj,
+                         struct bin_attribute *bin_attr,
+                         char *buf, loff_t off, size_t count)
 {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@ -176,8 +179,9 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
 }
 
 static ssize_t
-qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_write_optrom(struct kobject *kobj,
+                          struct bin_attribute *bin_attr,
+                          char *buf, loff_t off, size_t count)
 {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@ -198,7 +202,6 @@ static struct bin_attribute sysfs_optrom_attr = {
        .attr = {
                .name = "optrom",
                .mode = S_IRUSR | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = OPTROM_SIZE_24XX,
        .read = qla2x00_sysfs_read_optrom,
@@ -206,8 +209,9 @@ static struct bin_attribute sysfs_optrom_attr = {
 };
 
 static ssize_t
-qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
+                              struct bin_attribute *bin_attr,
+                              char *buf, loff_t off, size_t count)
 {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@ -279,15 +283,15 @@ static struct bin_attribute sysfs_optrom_ctl_attr = {
        .attr = {
                .name = "optrom_ctl",
                .mode = S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = 0,
        .write = qla2x00_sysfs_write_optrom_ctl,
 };
 
 static ssize_t
-qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_read_vpd(struct kobject *kobj,
+                      struct bin_attribute *bin_attr,
+                      char *buf, loff_t off, size_t count)
 {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@ -305,8 +309,9 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
 }
 
 static ssize_t
-qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_write_vpd(struct kobject *kobj,
+                       struct bin_attribute *bin_attr,
+                       char *buf, loff_t off, size_t count)
 {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@ -327,7 +332,6 @@ static struct bin_attribute sysfs_vpd_attr = {
        .attr = {
                .name = "vpd",
                .mode = S_IRUSR | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = 0,
        .read = qla2x00_sysfs_read_vpd,
@@ -335,8 +339,9 @@ static struct bin_attribute sysfs_vpd_attr = {
 };
 
 static ssize_t
-qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_read_sfp(struct kobject *kobj,
+                      struct bin_attribute *bin_attr,
+                      char *buf, loff_t off, size_t count)
 {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@ -375,7 +380,6 @@ static struct bin_attribute sysfs_sfp_attr = {
        .attr = {
                .name = "sfp",
                .mode = S_IRUSR | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = SFP_DEV_SIZE * 2,
        .read = qla2x00_sysfs_read_sfp,
index 2a45aec4ff29e6499a36456d24f6f496caf9ff4a..cf94f8636ba5af6b5504d5acb6995f0e9a7aaeae 100644 (file)
@@ -296,7 +296,7 @@ qla24xx_pci_config(scsi_qla_host_t *ha)
        d &= ~PCI_ROM_ADDRESS_ENABLE;
        pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
 
-       pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->chip_revision);
+       ha->chip_revision = ha->pdev->revision;
 
        /* Get PCI bus information. */
        spin_lock_irqsave(&ha->hardware_lock, flags);
index 315ea99164566b01458c4a1d676b7b1aa37fdb83..2adbed4e10f350ac753d7db2f1be860eb01e6243 100644 (file)
@@ -556,7 +556,7 @@ choice
 
 config SERIAL_BFIN_DMA
        bool "DMA mode"
-       depends on DMA_UNCACHED_1M
+       depends on DMA_UNCACHED_1M && !KGDB_UART
        help
          This driver works under DMA mode. If this option is selected, the
          blackfin simple dma driver is also enabled.
@@ -599,7 +599,7 @@ config UART0_RTS_PIN
 
 config SERIAL_BFIN_UART1
        bool "Enable UART1"
-       depends on SERIAL_BFIN && (BF534 || BF536 || BF537)
+       depends on SERIAL_BFIN && (BF534 || BF536 || BF537 || BF54x)
        help
          Enable UART1
 
@@ -612,18 +612,58 @@ config BFIN_UART1_CTSRTS
 
 config UART1_CTS_PIN
        int "UART1 CTS pin"
-       depends on BFIN_UART1_CTSRTS
+       depends on BFIN_UART1_CTSRTS && (BF53x || BF561)
        default -1
        help
          Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
 
 config UART1_RTS_PIN
        int "UART1 RTS pin"
-       depends on BFIN_UART1_CTSRTS
+       depends on BFIN_UART1_CTSRTS && (BF53x || BF561)
        default -1
        help
          Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
 
+config SERIAL_BFIN_UART2
+       bool "Enable UART2"
+       depends on SERIAL_BFIN && (BF54x)
+       help
+         Enable UART2
+
+config BFIN_UART2_CTSRTS
+       bool "Enable UART2 hardware flow control"
+       depends on SERIAL_BFIN_UART2
+       help
+         Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
+         signal.
+
+config UART2_CTS_PIN
+       int "UART2 CTS pin"
+       depends on BFIN_UART2_CTSRTS
+       default -1
+       help
+         Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
+
+config UART2_RTS_PIN
+       int "UART2 RTS pin"
+       depends on BFIN_UART2_CTSRTS
+       default -1
+       help
+         Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
+
+config SERIAL_BFIN_UART3
+       bool "Enable UART3"
+       depends on SERIAL_BFIN && (BF54x)
+       help
+         Enable UART3
+
+config BFIN_UART3_CTSRTS
+       bool "Enable UART3 hardware flow control"
+       depends on SERIAL_BFIN_UART3
+       help
+         Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
+         signal.
+
 config SERIAL_IMX
        bool "IMX serial port support"
        depends on ARM && ARCH_IMX
index 22569bd5d821e37e7f0b9f5aaaf15909831032dc..66c92bc36f3d1ae51cabbada195a73300dccbf27 100644 (file)
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 
+#ifdef CONFIG_KGDB_UART
+#include <linux/kgdb.h>
+#include <asm/irq_regs.h>
+#endif
+
 #include <asm/gpio.h>
 #include <asm/mach/bfin_serial_5xx.h>
 
@@ -81,8 +86,21 @@ static void bfin_serial_stop_tx(struct uart_port *port)
 {
        struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
 
+#ifdef CONFIG_BF54x
+       while (!(UART_GET_LSR(uart) & TEMT))
+               continue;
+#endif
+
 #ifdef CONFIG_SERIAL_BFIN_DMA
        disable_dma(uart->tx_dma_channel);
+#else
+#ifdef CONFIG_BF54x
+       /* Waiting for Transmission Finished */
+       while (!(UART_GET_LSR(uart) & TFI))
+               continue;
+       /* Clear TFI bit */
+       UART_PUT_LSR(uart, TFI);
+       UART_CLEAR_IER(uart, ETBEI);
 #else
        unsigned short ier;
 
@@ -90,6 +108,7 @@ static void bfin_serial_stop_tx(struct uart_port *port)
        ier &= ~ETBEI;
        UART_PUT_IER(uart, ier);
 #endif
+#endif
 }
 
 /*
@@ -101,6 +120,9 @@ static void bfin_serial_start_tx(struct uart_port *port)
 
 #ifdef CONFIG_SERIAL_BFIN_DMA
        bfin_serial_dma_tx_chars(uart);
+#else
+#ifdef CONFIG_BF54x
+       UART_SET_IER(uart, ETBEI);
 #else
        unsigned short ier;
        ier = UART_GET_IER(uart);
@@ -108,6 +130,7 @@ static void bfin_serial_start_tx(struct uart_port *port)
        UART_PUT_IER(uart, ier);
        bfin_serial_tx_chars(uart);
 #endif
+#endif
 }
 
 /*
@@ -116,11 +139,18 @@ static void bfin_serial_start_tx(struct uart_port *port)
 static void bfin_serial_stop_rx(struct uart_port *port)
 {
        struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+#ifdef CONFIG_BF54x
+       UART_CLEAR_IER(uart, ERBFI);
+#else
        unsigned short ier;
 
        ier = UART_GET_IER(uart);
+#ifdef CONFIG_KGDB_UART
+       if (uart->port.line != CONFIG_KGDB_UART_PORT)
+#endif
        ier &= ~ERBFI;
        UART_PUT_IER(uart, ier);
+#endif
 }
 
 /*
@@ -130,6 +160,49 @@ static void bfin_serial_enable_ms(struct uart_port *port)
 {
 }
 
+#ifdef CONFIG_KGDB_UART
+static int kgdb_entry_state;
+
+void kgdb_put_debug_char(int chr)
+{
+       struct bfin_serial_port *uart;
+       
+       if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
+               uart = &bfin_serial_ports[0];
+       else
+               uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+       
+       while (!(UART_GET_LSR(uart) & THRE)) {
+               __builtin_bfin_ssync();
+       }
+       UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB));
+       __builtin_bfin_ssync();
+       UART_PUT_CHAR(uart, (unsigned char)chr);
+       __builtin_bfin_ssync();
+}
+
+int kgdb_get_debug_char(void)
+{
+       struct bfin_serial_port *uart;
+       unsigned char chr;
+
+       if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
+               uart = &bfin_serial_ports[0];
+       else
+               uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+       
+       while(!(UART_GET_LSR(uart) & DR)) {
+               __builtin_bfin_ssync();
+       }
+       UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB));
+       __builtin_bfin_ssync();
+       chr = UART_GET_CHAR(uart);
+       __builtin_bfin_ssync();
+
+       return chr;
+}
+#endif
+
 #ifdef CONFIG_SERIAL_BFIN_PIO
 static void local_put_char(struct bfin_serial_port *uart, char ch)
 {
@@ -152,6 +225,9 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
 {
        struct tty_struct *tty = uart->port.info->tty;
        unsigned int status, ch, flg;
+#ifdef CONFIG_KGDB_UART
+       struct pt_regs *regs = get_irq_regs();
+#endif
 #ifdef BF533_FAMILY
        static int in_break = 0;
 #endif
@@ -160,6 +236,27 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
        ch = UART_GET_CHAR(uart);
        uart->port.icount.rx++;
 
+#ifdef CONFIG_KGDB_UART
+       if (uart->port.line == CONFIG_KGDB_UART_PORT) {
+               if (uart->port.cons->index == CONFIG_KGDB_UART_PORT && ch == 0x1) { /* Ctrl + A */
+                       kgdb_breakkey_pressed(regs);
+                       return;
+               } else if (kgdb_entry_state == 0 && ch == '$') {/* connection from KGDB */
+                       kgdb_entry_state = 1;
+               } else if (kgdb_entry_state == 1 && ch == 'q') {
+                       kgdb_entry_state = 0;
+                       kgdb_breakkey_pressed(regs);
+                       return;
+               } else if (ch == 0x3) {/* Ctrl + C */
+                       kgdb_entry_state = 0;
+                       kgdb_breakkey_pressed(regs);
+                       return;
+               } else {
+                       kgdb_entry_state = 0;
+               }
+       }
+#endif
 #ifdef BF533_FAMILY
        /* The BF533 family of processors have a nice misbehavior where
         * they continuously generate characters for a "single" break.
@@ -250,10 +347,21 @@ static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
 {
        struct bfin_serial_port *uart = dev_id;
 
+#ifdef CONFIG_BF54x
+       unsigned short status;
+       spin_lock(&uart->port.lock);
+       status = UART_GET_LSR(uart);
+       while ((UART_GET_IER(uart) & ERBFI) && (status & DR)) {
+               bfin_serial_rx_chars(uart);
+               status = UART_GET_LSR(uart);
+       }
+       spin_unlock(&uart->port.lock);
+#else
        spin_lock(&uart->port.lock);
        while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_RX_READY)
                bfin_serial_rx_chars(uart);
        spin_unlock(&uart->port.lock);
+#endif
        return IRQ_HANDLED;
 }
 
@@ -261,10 +369,21 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
 {
        struct bfin_serial_port *uart = dev_id;
 
+#ifdef CONFIG_BF54x
+       unsigned short status;
+       spin_lock(&uart->port.lock);
+       status = UART_GET_LSR(uart);
+       while ((UART_GET_IER(uart) & ETBEI) && (status & THRE)) {
+               bfin_serial_tx_chars(uart);
+               status = UART_GET_LSR(uart);
+       }
+       spin_unlock(&uart->port.lock);
+#else
        spin_lock(&uart->port.lock);
        while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_TX_READY)
                bfin_serial_tx_chars(uart);
        spin_unlock(&uart->port.lock);
+#endif
        return IRQ_HANDLED;
 }
 
@@ -275,7 +394,6 @@ static void bfin_serial_do_work(struct work_struct *work)
 
        bfin_serial_mctrl_check(uart);
 }
-
 #endif
 
 #ifdef CONFIG_SERIAL_BFIN_DMA
@@ -324,9 +442,13 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
        set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
        set_dma_x_modify(uart->tx_dma_channel, 1);
        enable_dma(uart->tx_dma_channel);
+#ifdef CONFIG_BF54x
+       UART_SET_IER(uart, ETBEI);
+#else
        ier = UART_GET_IER(uart);
        ier |= ETBEI;
        UART_PUT_IER(uart, ier);
+#endif
        spin_unlock_irqrestore(&uart->port.lock, flags);
 }
 
@@ -406,9 +528,13 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
        if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
                clear_dma_irqstat(uart->tx_dma_channel);
                disable_dma(uart->tx_dma_channel);
+#ifdef CONFIG_BF54x
+               UART_CLEAR_IER(uart, ETBEI);
+#else
                ier = UART_GET_IER(uart);
                ier &= ~ETBEI;
                UART_PUT_IER(uart, ier);
+#endif
                xmit->tail = (xmit->tail+uart->tx_count) &(UART_XMIT_SIZE -1);
                uart->port.icount.tx+=uart->tx_count;
 
@@ -571,7 +697,11 @@ static int bfin_serial_startup(struct uart_port *port)
        uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
        add_timer(&(uart->rx_dma_timer));
 #else
+# ifdef        CONFIG_KGDB_UART
+       if (uart->port.line != CONFIG_KGDB_UART_PORT && request_irq
+# else
        if (request_irq
+# endif
            (uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED,
             "BFIN_UART_RX", uart)) {
                printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");
@@ -586,7 +716,11 @@ static int bfin_serial_startup(struct uart_port *port)
                return -EBUSY;
        }
 #endif
+#ifdef CONFIG_BF54x
+       UART_SET_IER(uart, ERBFI);
+#else
        UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI);
+#endif
        return 0;
 }
 
@@ -601,6 +735,9 @@ static void bfin_serial_shutdown(struct uart_port *port)
        free_dma(uart->rx_dma_channel);
        del_timer(&(uart->rx_dma_timer));
 #else
+#ifdef CONFIG_KGDB_UART
+       if (uart->port.line != CONFIG_KGDB_UART_PORT)
+#endif
        free_irq(uart->port.irq, uart);
        free_irq(uart->port.irq+1, uart);
 #endif
@@ -674,29 +811,41 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
 
        /* Disable UART */
        ier = UART_GET_IER(uart);
+#ifdef CONFIG_BF54x
+       UART_CLEAR_IER(uart, 0xF);
+#else
        UART_PUT_IER(uart, 0);
+#endif
 
+#ifndef CONFIG_BF54x
        /* Set DLAB in LCR to Access DLL and DLH */
        val = UART_GET_LCR(uart);
        val |= DLAB;
        UART_PUT_LCR(uart, val);
        SSYNC();
+#endif
 
        UART_PUT_DLL(uart, quot & 0xFF);
        SSYNC();
        UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
        SSYNC();
 
+#ifndef CONFIG_BF54x
        /* Clear DLAB in LCR to Access THR RBR IER */
        val = UART_GET_LCR(uart);
        val &= ~DLAB;
        UART_PUT_LCR(uart, val);
        SSYNC();
+#endif
 
        UART_PUT_LCR(uart, lcr);
 
        /* Enable UART */
+#ifdef CONFIG_BF54x
+       UART_SET_IER(uart, ier);
+#else
        UART_PUT_IER(uart, ier);
+#endif
 
        val = UART_GET_GCTL(uart);
        val |= UCEN;
@@ -808,15 +957,15 @@ static void __init bfin_serial_init_ports(void)
                        bfin_serial_resource[i].uart_rts_pin;
 #endif
                bfin_serial_hw_init(&bfin_serial_ports[i]);
-
        }
+
 }
 
 #ifdef CONFIG_SERIAL_BFIN_CONSOLE
 static void bfin_serial_console_putchar(struct uart_port *port, int ch)
 {
        struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-       while (!(UART_GET_LSR(uart)))
+       while (!(UART_GET_LSR(uart) & THRE))
                barrier();
        UART_PUT_CHAR(uart, ch);
        SSYNC();
@@ -868,18 +1017,22 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
                        case 2: *bits = 7; break;
                        case 3: *bits = 8; break;
                }
+#ifndef CONFIG_BF54x
                /* Set DLAB in LCR to Access DLL and DLH */
                val = UART_GET_LCR(uart);
                val |= DLAB;
                UART_PUT_LCR(uart, val);
+#endif
 
                dll = UART_GET_DLL(uart);
                dlh = UART_GET_DLH(uart);
 
+#ifndef CONFIG_BF54x
                /* Clear DLAB in LCR to Access THR RBR IER */
                val = UART_GET_LCR(uart);
                val &= ~DLAB;
                UART_PUT_LCR(uart, val);
+#endif
 
                *baud = get_sclk() / (16*(dll | dlh << 8));
        }
@@ -931,6 +1084,10 @@ static int __init bfin_serial_rs_console_init(void)
 {
        bfin_serial_init_ports();
        register_console(&bfin_serial_console);
+#ifdef CONFIG_KGDB_UART
+       kgdb_entry_state = 0;
+       init_kgdb_uart();
+#endif
        return 0;
 }
 console_initcall(bfin_serial_rs_console_init);
@@ -1023,6 +1180,10 @@ static struct platform_driver bfin_serial_driver = {
 static int __init bfin_serial_init(void)
 {
        int ret;
+#ifdef CONFIG_KGDB_UART
+       struct bfin_serial_port *uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+       struct termios t;
+#endif
 
        pr_info("Serial: Blackfin serial driver\n");
 
@@ -1036,6 +1197,21 @@ static int __init bfin_serial_init(void)
                        uart_unregister_driver(&bfin_serial_reg);
                }
        }
+#ifdef CONFIG_KGDB_UART
+       if (uart->port.cons->index != CONFIG_KGDB_UART_PORT) {
+               request_irq(uart->port.irq, bfin_serial_int,
+                       IRQF_DISABLED, "BFIN_UART_RX", uart);
+               pr_info("Request irq for kgdb uart port\n");
+               UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI);
+               __builtin_bfin_ssync();
+               t.c_cflag = CS8|B57600;
+               t.c_iflag = 0;
+               t.c_oflag = 0;
+               t.c_lflag = ICANON;
+               t.c_line = CONFIG_KGDB_UART_PORT;
+               bfin_serial_set_termios(&uart->port, &t, &t);
+       }
+#endif
        return ret;
 }
 
index 81792e6eeb2d045bf27069a10f58417a84805642..6767ee381cd1b4645056012ba3704c05177389a0 100644 (file)
@@ -88,7 +88,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        spin_lock_init(&brd->bd_intr_lock);
 
        /* store which revision we have */
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
+       brd->rev = pdev->revision;
 
        brd->irq = pdev->irq;
 
index cf0e663b42ed97781c353f98cd8abb779b592a3c..85309acb75f634da4e3ef3b97590dc5d559ecb79 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for NEC VR4100 series Serial Interface Unit.
  *
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2004-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
  *
  *  Based on drivers/serial/8250.c, by Russell King.
  *
 #endif
 
 #include <linux/console.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/ioport.h>
+#include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/tty_flip.h>
 
 #include <asm/io.h>
-#include <asm/vr41xx/irq.h>
 #include <asm/vr41xx/siu.h>
 #include <asm/vr41xx/vr41xx.h>
 
-#define SIU_PORTS_MAX  2
 #define SIU_BAUD_BASE  1152000
 #define SIU_MAJOR      204
 #define SIU_MINOR_BASE 82
  #define IRUSESEL      0x02
  #define SIRSEL                0x01
 
-struct siu_port {
-       unsigned int type;
-       unsigned int irq;
-       unsigned long start;
-};
-
-static const struct siu_port siu_type1_ports[] = {
-       {       .type           = PORT_VR41XX_SIU,
-               .irq            = SIU_IRQ,
-               .start          = 0x0c000000UL,         },
-};
-
-#define SIU_TYPE1_NR_PORTS     (sizeof(siu_type1_ports) / sizeof(struct siu_port))
-
-static const struct siu_port siu_type2_ports[] = {
-       {       .type           = PORT_VR41XX_SIU,
-               .irq            = SIU_IRQ,
-               .start          = 0x0f000800UL,         },
-       {       .type           = PORT_VR41XX_DSIU,
-               .irq            = DSIU_IRQ,
-               .start          = 0x0f000820UL,         },
+static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = {
+       [0 ... SIU_PORTS_MAX-1] = {
+               .lock   = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock),
+               .irq    = -1,
+       },
 };
 
-#define SIU_TYPE2_NR_PORTS     (sizeof(siu_type2_ports) / sizeof(struct siu_port))
-
-static struct uart_port siu_uart_ports[SIU_PORTS_MAX];
 static uint8_t lsr_break_flag[SIU_PORTS_MAX];
 
 #define siu_read(port, offset)         readb((port)->membase + (offset))
@@ -110,7 +89,6 @@ void vr41xx_select_siu_interface(siu_interface_t interface)
 
        spin_unlock_irqrestore(&port->lock, flags);
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_select_siu_interface);
 
 void vr41xx_use_irda(irda_use_t use)
@@ -132,7 +110,6 @@ void vr41xx_use_irda(irda_use_t use)
 
        spin_unlock_irqrestore(&port->lock, flags);
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_use_irda);
 
 void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed)
@@ -166,7 +143,6 @@ void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed)
 
        spin_unlock_irqrestore(&port->lock, flags);
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_select_irda_module);
 
 static inline void siu_clear_fifo(struct uart_port *port)
@@ -177,21 +153,6 @@ static inline void siu_clear_fifo(struct uart_port *port)
        siu_write(port, UART_FCR, 0);
 }
 
-static inline int siu_probe_ports(void)
-{
-       switch (current_cpu_data.cputype) {
-       case CPU_VR4111:
-       case CPU_VR4121:
-               return SIU_TYPE1_NR_PORTS;
-       case CPU_VR4122:
-       case CPU_VR4131:
-       case CPU_VR4133:
-               return SIU_TYPE2_NR_PORTS;
-       }
-
-       return 0;
-}
-
 static inline unsigned long siu_port_size(struct uart_port *port)
 {
        switch (port->type) {
@@ -206,21 +167,10 @@ static inline unsigned long siu_port_size(struct uart_port *port)
 
 static inline unsigned int siu_check_type(struct uart_port *port)
 {
-       switch (current_cpu_data.cputype) {
-       case CPU_VR4111:
-       case CPU_VR4121:
-               if (port->line == 0)
-                       return PORT_VR41XX_SIU;
-               break;
-       case CPU_VR4122:
-       case CPU_VR4131:
-       case CPU_VR4133:
-               if (port->line == 0)
-                       return PORT_VR41XX_SIU;
-               else if (port->line == 1)
-                       return PORT_VR41XX_DSIU;
-               break;
-       }
+       if (port->line == 0)
+               return PORT_VR41XX_SIU;
+       if (port->line == 1 && port->irq != -1)
+               return PORT_VR41XX_DSIU;
 
        return PORT_UNKNOWN;
 }
@@ -751,44 +701,34 @@ static struct uart_ops siu_uart_ops = {
        .verify_port    = siu_verify_port,
 };
 
-static int siu_init_ports(void)
+static int siu_init_ports(struct platform_device *pdev)
 {
-       const struct siu_port *siu;
        struct uart_port *port;
-       int i, num;
+       struct resource *res;
+       int *type = pdev->dev.platform_data;
+       int i;
 
-       switch (current_cpu_data.cputype) {
-       case CPU_VR4111:
-       case CPU_VR4121:
-               siu = siu_type1_ports;
-               break;
-       case CPU_VR4122:
-       case CPU_VR4131:
-       case CPU_VR4133:
-               siu = siu_type2_ports;
-               break;
-       default:
+       if (!type)
                return 0;
-       }
 
        port = siu_uart_ports;
-       num = siu_probe_ports();
-       for (i = 0; i < num; i++) {
-               spin_lock_init(&port->lock);
-               port->irq = siu->irq;
+       for (i = 0; i < SIU_PORTS_MAX; i++) {
+               port->type = type[i];
+               if (port->type == PORT_UNKNOWN)
+                       continue;
+               port->irq = platform_get_irq(pdev, i);
                port->uartclk = SIU_BAUD_BASE * 16;
                port->fifosize = 16;
                port->regshift = 0;
                port->iotype = UPIO_MEM;
                port->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-               port->type = siu->type;
                port->line = i;
-               port->mapbase = siu->start;
-               siu++;
+               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               port->mapbase = res->start;
                port++;
        }
 
-       return num;
+       return i;
 }
 
 #ifdef CONFIG_SERIAL_VR41XX_CONSOLE
@@ -883,13 +823,9 @@ static struct console siu_console = {
 static int __devinit siu_console_init(void)
 {
        struct uart_port *port;
-       int num, i;
-
-       num = siu_init_ports();
-       if (num <= 0)
-               return -ENODEV;
+       int i;
 
-       for (i = 0; i < num; i++) {
+       for (i = 0; i < SIU_PORTS_MAX; i++) {
                port = &siu_uart_ports[i];
                port->ops = &siu_uart_ops;
        }
@@ -920,7 +856,7 @@ static int __devinit siu_probe(struct platform_device *dev)
        struct uart_port *port;
        int num, i, retval;
 
-       num = siu_init_ports();
+       num = siu_init_ports(dev);
        if (num <= 0)
                return -ENODEV;
 
@@ -998,8 +934,6 @@ static int siu_resume(struct platform_device *dev)
        return 0;
 }
 
-static struct platform_device *siu_platform_device;
-
 static struct platform_driver siu_device_driver = {
        .probe          = siu_probe,
        .remove         = __devexit_p(siu_remove),
@@ -1013,29 +947,12 @@ static struct platform_driver siu_device_driver = {
 
 static int __init vr41xx_siu_init(void)
 {
-       int retval;
-
-       siu_platform_device = platform_device_alloc("SIU", -1);
-       if (!siu_platform_device)
-               return -ENOMEM;
-
-       retval = platform_device_add(siu_platform_device);
-       if (retval < 0) {
-               platform_device_put(siu_platform_device);
-               return retval;
-       }
-
-       retval = platform_driver_register(&siu_device_driver);
-       if (retval < 0)
-               platform_device_unregister(siu_platform_device);
-
-       return retval;
+       return platform_driver_register(&siu_device_driver);
 }
 
 static void __exit vr41xx_siu_exit(void)
 {
        platform_driver_unregister(&siu_device_driver);
-       platform_device_unregister(siu_platform_device);
 }
 
 module_init(vr41xx_siu_init);
index 8efa07e8b8c2a7bef31ce118109b622e42de210d..e007833cca59adfd955b17c7dbcf5adee3b5e3b7 100644 (file)
@@ -111,7 +111,8 @@ at25_ee_read(
 }
 
 static ssize_t
-at25_bin_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+             char *buf, loff_t off, size_t count)
 {
        struct device           *dev;
        struct at25_data        *at25;
@@ -236,7 +237,8 @@ at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count)
 }
 
 static ssize_t
-at25_bin_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+              char *buf, loff_t off, size_t count)
 {
        struct device           *dev;
        struct at25_data        *at25;
@@ -314,7 +316,6 @@ static int at25_probe(struct spi_device *spi)
         */
        at25->bin.attr.name = "eeprom";
        at25->bin.attr.mode = S_IRUSR;
-       at25->bin.attr.owner = THIS_MODULE;
        at25->bin.read = at25_bin_read;
 
        at25->bin.size = at25->chip.byte_len;
index 4fff61b32dcbdbf6bc25d1ba0808d0e58f249217..ed979f13908a3f358d08e97786a4a65e27138d38 100644 (file)
@@ -136,14 +136,14 @@ struct dec_serial *zs_chain;      /* list of all channels */
 struct tty_struct zs_ttys[NUM_CHANNELS];
 
 #ifdef CONFIG_SERIAL_DEC_CONSOLE
-static struct console sercons;
+static struct console zs_console;
 #endif
 #if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
    !defined(MODULE)
 static unsigned long break_pressed; /* break, really ... */
 #endif
 
-static unsigned char zs_init_regs[16] = {
+static unsigned char zs_init_regs[16] __initdata = {
        0,                              /* write 0 */
        0,                              /* write 1 */
        0,                              /* write 2 */
@@ -383,7 +383,7 @@ static void receive_chars(struct dec_serial *info)
 
 #if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
    !defined(MODULE)
-               if (break_pressed && info->line == sercons.index) {
+               if (break_pressed && info->line == zs_console.index) {
                        /* Ignore the null char got when BREAK is removed.  */
                        if (ch == 0)
                                continue;
@@ -446,7 +446,7 @@ static void status_handle(struct dec_serial *info)
        if ((stat & BRK_ABRT) && !(info->read_reg_zero & BRK_ABRT)) {
 #if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
    !defined(MODULE)
-               if (info->line == sercons.index) {
+               if (info->line == zs_console.index) {
                        if (!break_pressed)
                                break_pressed = jiffies;
                } else
@@ -1557,9 +1557,9 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
        }
 
 #ifdef CONFIG_SERIAL_DEC_CONSOLE
-       if (sercons.cflag && sercons.index == line) {
-               tty->termios->c_cflag = sercons.cflag;
-               sercons.cflag = 0;
+       if (zs_console.cflag && zs_console.index == line) {
+               tty->termios->c_cflag = zs_console.cflag;
+               zs_console.cflag = 0;
                change_speed(info);
        }
 #endif
@@ -1581,7 +1581,7 @@ static void __init show_serial_version(void)
 /*  Initialize Z8530s zs_channels
  */
 
-static void probe_sccs(void)
+static void __init probe_sccs(void)
 {
        struct dec_serial **pp;
        int i, n, n_chips = 0, n_channels, chip, channel;
@@ -1923,7 +1923,7 @@ static struct tty_driver *serial_console_device(struct console *c, int *index)
  *     - initialize the serial port
  *     Return non-zero if we didn't find a serial port.
  */
-static int serial_console_setup(struct console *co, char *options)
+static int __init serial_console_setup(struct console *co, char *options)
 {
        struct dec_serial *info;
        int baud = 9600;
@@ -2069,7 +2069,7 @@ static int serial_console_setup(struct console *co, char *options)
        return 0;
 }
 
-static struct console sercons = {
+static struct console zs_console = {
        .name           = "ttyS",
        .write          = serial_console_write,
        .device         = serial_console_device,
@@ -2083,7 +2083,7 @@ static struct console sercons = {
  */
 void __init zs_serial_console_init(void)
 {
-       register_console(&sercons);
+       register_console(&zs_console);
 }
 #endif /* ifdef CONFIG_SERIAL_DEC_CONSOLE */
 
index 15499b7e33f4855b1f6bb8f440d06672a8388c86..071b9675a7819dff38f5128c1d23f635f12b26a8 100644 (file)
@@ -2,8 +2,12 @@
 # USB device configuration
 #
 
-menu "USB support"
+menuconfig USB_SUPPORT
+       bool "USB support"
        depends on HAS_IOMEM
+       default y
+
+if USB_SUPPORT
 
 # Host-side USB depends on having a host controller
 # NOTE:  dummy_hcd is always an option, but it's ignored here ...
@@ -12,6 +16,7 @@ config USB_ARCH_HAS_HCD
        boolean
        default y if USB_ARCH_HAS_OHCI
        default y if USB_ARCH_HAS_EHCI
+       default y if PCMCIA                             # sl811_cs
        default y if ARM                                # SL-811
        default PCI
 
@@ -130,5 +135,4 @@ source "drivers/usb/atm/Kconfig"
 
 source "drivers/usb/gadget/Kconfig"
 
-endmenu
-
+endif # USB_SUPPORT
index 72464b586990cdaab565bbb1958cd5212a1629ec..befff5f9d58c59ce1b5fc19545382ca8b9116b69 100644 (file)
@@ -15,7 +15,7 @@ obj-$(CONFIG_USB_OHCI_HCD)    += host/
 obj-$(CONFIG_USB_UHCI_HCD)     += host/
 obj-$(CONFIG_USB_SL811_HCD)    += host/
 obj-$(CONFIG_USB_U132_HCD)     += host/
-obj-$(CONFIG_USB_OHCI_AT91)    += host/
+obj-$(CONFIG_USB_R8A66597_HCD) += host/
 
 obj-$(CONFIG_USB_ACM)          += class/
 obj-$(CONFIG_USB_PRINTER)      += class/
index 8bcf7fe1dd80c7b531c417f5c58e565b8fd8653f..1bc884051e0f490dbae657df3bd085b5b8e568de 100644 (file)
@@ -171,7 +171,7 @@ struct cxacru_data {
        struct delayed_work poll_work;
        u32 card_info[CXINF_MAX];
        struct mutex poll_state_serialize;
-       int poll_state;
+       enum cxacru_poll_state poll_state;
 
        /* contol handles */
        struct mutex cm_serialize;
@@ -226,58 +226,48 @@ static ssize_t cxacru_sysfs_showattr_s8(s8 value, char *buf)
 
 static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf)
 {
-       if (unlikely(value < 0)) {
-               return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
-                                               value / 100, -value % 100);
-       } else {
-               return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
-                                               value / 100, value % 100);
-       }
+       return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
+                                       value / 100, abs(value) % 100);
 }
 
 static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
 {
-       switch (value) {
-       case 0: return snprintf(buf, PAGE_SIZE, "no\n");
-       case 1: return snprintf(buf, PAGE_SIZE, "yes\n");
-       default: return 0;
-       }
+       static char *str[] = { "no", "yes" };
+       if (unlikely(value >= ARRAY_SIZE(str)))
+               return snprintf(buf, PAGE_SIZE, "%u\n", value);
+       return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
 }
 
 static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
 {
-       switch (value) {
-       case 1: return snprintf(buf, PAGE_SIZE, "not connected\n");
-       case 2: return snprintf(buf, PAGE_SIZE, "connected\n");
-       case 3: return snprintf(buf, PAGE_SIZE, "lost\n");
-       default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
-       }
+       static char *str[] = { NULL, "not connected", "connected", "lost" };
+       if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
+               return snprintf(buf, PAGE_SIZE, "%u\n", value);
+       return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
 }
 
 static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf)
 {
-       switch (value) {
-       case 0: return snprintf(buf, PAGE_SIZE, "down\n");
-       case 1: return snprintf(buf, PAGE_SIZE, "attempting to activate\n");
-       case 2: return snprintf(buf, PAGE_SIZE, "training\n");
-       case 3: return snprintf(buf, PAGE_SIZE, "channel analysis\n");
-       case 4: return snprintf(buf, PAGE_SIZE, "exchange\n");
-       case 5: return snprintf(buf, PAGE_SIZE, "up\n");
-       case 6: return snprintf(buf, PAGE_SIZE, "waiting\n");
-       case 7: return snprintf(buf, PAGE_SIZE, "initialising\n");
-       default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
-       }
+       static char *str[] = { "down", "attempting to activate",
+               "training", "channel analysis", "exchange", "up",
+               "waiting", "initialising"
+       };
+       if (unlikely(value >= ARRAY_SIZE(str)))
+               return snprintf(buf, PAGE_SIZE, "%u\n", value);
+       return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
 }
 
 static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
 {
-       switch (value) {
-       case 0: return 0;
-       case 1: return snprintf(buf, PAGE_SIZE, "ANSI T1.413\n");
-       case 2: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.1 (G.DMT)\n");
-       case 3: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.2 (G.LITE)\n");
-       default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
-       }
+       static char *str[] = {
+                       NULL,
+                       "ANSI T1.413",
+                       "ITU-T G.992.1 (G.DMT)",
+                       "ITU-T G.992.2 (G.LITE)"
+       };
+       if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
+               return snprintf(buf, PAGE_SIZE, "%u\n", value);
+       return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
 }
 
 /*
@@ -308,11 +298,10 @@ static ssize_t cxacru_sysfs_show_adsl_state(struct device *dev,
        struct cxacru_data *instance = usbatm_instance->driver_data;
        u32 value = instance->card_info[CXINF_LINE_STARTABLE];
 
-       switch (value) {
-       case 0: return snprintf(buf, PAGE_SIZE, "running\n");
-       case 1: return snprintf(buf, PAGE_SIZE, "stopped\n");
-       default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
-       }
+       static char *str[] = { "running", "stopped" };
+       if (unlikely(value >= ARRAY_SIZE(str)))
+               return snprintf(buf, PAGE_SIZE, "%u\n", value);
+       return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
 }
 
 static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
index 0081c1d12687de6f8813efb11e0f338c7d7d28a5..cd51520c7e72e10286017998bf00081c8d8571cc 100644 (file)
@@ -1157,6 +1157,9 @@ static struct usb_device_id acm_ids[] = {
        { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
+       { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */
+       .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+       },
        { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
index 6778f9af794381ec0ae40df7253aa26f0bbddfbc..9a1478972bf5aee1cf75c5f70434d4e68c5fa83c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * usblp.c  Version 0.13
+ * usblp.c
  *
  * Copyright (c) 1999 Michael Gee      <michael@linuxspecific.com>
  * Copyright (c) 1999 Pavel Machek     <pavel@suse.cz>
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.13"
 #define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
 #define DRIVER_DESC "USB Printer Device Class driver"
 
 #define USBLP_BUF_SIZE         8192
+#define USBLP_BUF_SIZE_IN      1024
 #define USBLP_DEVICE_ID_SIZE   1024
 
 /* ioctls: */
@@ -127,14 +127,22 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
  */
 #define STATUS_BUF_SIZE                8
 
+/*
+ * Locks down the locking order:
+ * ->wmut locks wstatus.
+ * ->mut locks the whole usblp, except [rw]complete, and thus, by indirection,
+ * [rw]status. We only touch status when we know the side idle.
+ * ->lock locks what interrupt accesses.
+ */
 struct usblp {
        struct usb_device       *dev;                   /* USB device */
-       struct mutex            mut;                    /* locks this struct, especially "dev" */
-       char                    *writebuf;              /* write transfer_buffer */
+       struct mutex            wmut;
+       struct mutex            mut;
+       spinlock_t              lock;           /* locks rcomplete, wcomplete */
        char                    *readbuf;               /* read transfer_buffer */
        char                    *statusbuf;             /* status transfer_buffer */
-       struct urb              *readurb, *writeurb;    /* The urbs */
-       wait_queue_head_t       wait;                   /* Zzzzz ... */
+       struct usb_anchor       urbs;
+       wait_queue_head_t       rwait, wwait;
        int                     readcount;              /* Counter for reads */
        int                     ifnum;                  /* Interface number */
        struct usb_interface    *intf;                  /* The interface */
@@ -147,8 +155,9 @@ struct usblp {
        }                       protocol[USBLP_MAX_PROTOCOLS];
        int                     current_protocol;
        int                     minor;                  /* minor number of device */
-       int                     wcomplete;              /* writing is completed */
-       int                     rcomplete;              /* reading is completed */
+       int                     wcomplete, rcomplete;
+       int                     wstatus;        /* bytes written or error */
+       int                     rstatus;        /* bytes ready or error */
        unsigned int            quirks;                 /* quirks flags */
        unsigned char           used;                   /* True if open */
        unsigned char           present;                /* True if not disconnected */
@@ -166,9 +175,6 @@ static void usblp_dump(struct usblp *usblp) {
        dbg("dev=0x%p", usblp->dev);
        dbg("present=%d", usblp->present);
        dbg("readbuf=0x%p", usblp->readbuf);
-       dbg("writebuf=0x%p", usblp->writebuf);
-       dbg("readurb=0x%p", usblp->readurb);
-       dbg("writeurb=0x%p", usblp->writeurb);
        dbg("readcount=%d", usblp->readcount);
        dbg("ifnum=%d", usblp->ifnum);
     for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
@@ -178,8 +184,8 @@ static void usblp_dump(struct usblp *usblp) {
     }
        dbg("current_protocol=%d", usblp->current_protocol);
        dbg("minor=%d", usblp->minor);
-       dbg("wcomplete=%d", usblp->wcomplete);
-       dbg("rcomplete=%d", usblp->rcomplete);
+       dbg("wstatus=%d", usblp->wstatus);
+       dbg("rstatus=%d", usblp->rstatus);
        dbg("quirks=%d", usblp->quirks);
        dbg("used=%d", usblp->used);
        dbg("bidir=%d", usblp->bidir);
@@ -222,6 +228,11 @@ static const struct quirk_printer_struct quirk_printers[] = {
        { 0, 0 }
 };
 
+static int usblp_wwait(struct usblp *usblp, int nonblock);
+static int usblp_wtest(struct usblp *usblp, int nonblock);
+static int usblp_rwait_and_lock(struct usblp *usblp, int nonblock);
+static int usblp_rtest(struct usblp *usblp, int nonblock);
+static int usblp_submit_read(struct usblp *usblp);
 static int usblp_select_alts(struct usblp *usblp);
 static int usblp_set_protocol(struct usblp *usblp, int protocol);
 static int usblp_cache_device_id_string(struct usblp *usblp);
@@ -279,33 +290,47 @@ static void usblp_bulk_read(struct urb *urb)
 {
        struct usblp *usblp = urb->context;
 
-       if (unlikely(!usblp || !usblp->dev || !usblp->used))
-               return;
-
-       if (unlikely(!usblp->present))
-               goto unplug;
-       if (unlikely(urb->status))
-               warn("usblp%d: nonzero read/write bulk status received: %d",
-                       usblp->minor, urb->status);
+       if (usblp->present && usblp->used) {
+               if (urb->status)
+                       printk(KERN_WARNING "usblp%d: "
+                           "nonzero read bulk status received: %d\n",
+                           usblp->minor, urb->status);
+       }
+       spin_lock(&usblp->lock);
+       if (urb->status < 0)
+               usblp->rstatus = urb->status;
+       else
+               usblp->rstatus = urb->actual_length;
        usblp->rcomplete = 1;
-unplug:
-       wake_up_interruptible(&usblp->wait);
+       wake_up(&usblp->rwait);
+       spin_unlock(&usblp->lock);
+
+       usb_free_urb(urb);
 }
 
 static void usblp_bulk_write(struct urb *urb)
 {
        struct usblp *usblp = urb->context;
 
-       if (unlikely(!usblp || !usblp->dev || !usblp->used))
-               return;
-       if (unlikely(!usblp->present))
-               goto unplug;
-       if (unlikely(urb->status))
-               warn("usblp%d: nonzero read/write bulk status received: %d",
-                       usblp->minor, urb->status);
+       if (usblp->present && usblp->used) {
+               if (urb->status)
+                       printk(KERN_WARNING "usblp%d: "
+                           "nonzero write bulk status received: %d\n",
+                           usblp->minor, urb->status);
+       }
+       spin_lock(&usblp->lock);
+       if (urb->status < 0)
+               usblp->wstatus = urb->status;
+       else
+               usblp->wstatus = urb->actual_length;
        usblp->wcomplete = 1;
-unplug:
-       wake_up_interruptible(&usblp->wait);
+       wake_up(&usblp->wwait);
+       spin_unlock(&usblp->lock);
+
+       /* XXX Use usb_setup_bulk_urb when available. Talk to Marcel. */
+       kfree(urb->transfer_buffer);
+       urb->transfer_buffer = NULL;    /* Not refcounted, so to be safe... */
+       usb_free_urb(urb);
 }
 
 /*
@@ -322,7 +347,8 @@ static int usblp_check_status(struct usblp *usblp, int err)
        error = usblp_read_status (usblp, usblp->statusbuf);
        if (error < 0) {
                if (printk_ratelimit())
-                       err("usblp%d: error %d reading printer status",
+                       printk(KERN_ERR
+                               "usblp%d: error %d reading printer status\n",
                                usblp->minor, error);
                return 0;
        }
@@ -336,8 +362,10 @@ static int usblp_check_status(struct usblp *usblp, int err)
        if (~status & LP_PSELECD)
                newerr = 2;
 
-       if (newerr != err)
-               info("usblp%d: %s", usblp->minor, usblp_messages[newerr]);
+       if (newerr != err) {
+               printk(KERN_INFO "usblp%d: %s\n",
+                  usblp->minor, usblp_messages[newerr]);
+       }
 
        return newerr;
 }
@@ -345,12 +373,9 @@ static int usblp_check_status(struct usblp *usblp, int err)
 static int handle_bidir (struct usblp *usblp)
 {
        if (usblp->bidir && usblp->used && !usblp->sleeping) {
-               usblp->readcount = 0;
-               usblp->readurb->dev = usblp->dev;
-               if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0)
+               if (usblp_submit_read(usblp) < 0)
                        return -EIO;
        }
-
        return 0;
 }
 
@@ -403,11 +428,9 @@ static int usblp_open(struct inode *inode, struct file *file)
        usblp->used = 1;
        file->private_data = usblp;
 
-       usblp->writeurb->transfer_buffer_length = 0;
        usblp->wcomplete = 1; /* we begin writeable */
+       usblp->wstatus = 0;
        usblp->rcomplete = 0;
-       usblp->writeurb->status = 0;
-       usblp->readurb->status = 0;
 
        if (handle_bidir(usblp) < 0) {
                usblp->used = 0;
@@ -421,20 +444,17 @@ out:
 
 static void usblp_cleanup (struct usblp *usblp)
 {
-       info("usblp%d: removed", usblp->minor);
+       printk(KERN_INFO "usblp%d: removed\n", usblp->minor);
 
+       kfree(usblp->readbuf);
        kfree (usblp->device_id_string);
        kfree (usblp->statusbuf);
-       usb_free_urb(usblp->writeurb);
-       usb_free_urb(usblp->readurb);
        kfree (usblp);
 }
 
 static void usblp_unlink_urbs(struct usblp *usblp)
 {
-       usb_kill_urb(usblp->writeurb);
-       if (usblp->bidir)
-               usb_kill_urb(usblp->readurb);
+       usb_kill_anchored_urbs(&usblp->urbs);
 }
 
 static int usblp_release(struct inode *inode, struct file *file)
@@ -455,10 +475,18 @@ static int usblp_release(struct inode *inode, struct file *file)
 /* No kernel lock - fine */
 static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait)
 {
+       int ret;
+       unsigned long flags;
+
        struct usblp *usblp = file->private_data;
-       poll_wait(file, &usblp->wait, wait);
-       return ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN  | POLLRDNORM)
+       /* Should we check file->f_mode & FMODE_WRITE before poll_wait()? */
+       poll_wait(file, &usblp->rwait, wait);
+       poll_wait(file, &usblp->wwait, wait);
+       spin_lock_irqsave(&usblp->lock, flags);
+       ret = ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN  | POLLRDNORM)
                               | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM);
+       spin_unlock_irqrestore(&usblp->lock, flags);
+       return ret;
 }
 
 static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -632,10 +660,11 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                switch (cmd) {
 
                        case LPGETSTATUS:
-                               if (usblp_read_status(usblp, usblp->statusbuf)) {
+                               if ((retval = usblp_read_status(usblp, usblp->statusbuf))) {
                                        if (printk_ratelimit())
-                                               err("usblp%d: failed reading printer status",
-                                                       usblp->minor);
+                                               printk(KERN_ERR "usblp%d:"
+                                                   "failed reading printer status (%d)\n",
+                                                   usblp->minor, retval);
                                        retval = -EIO;
                                        goto done;
                                }
@@ -656,168 +685,303 @@ done:
 static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
        struct usblp *usblp = file->private_data;
-       int timeout, intr, rv, err = 0, transfer_length = 0;
-       size_t writecount = 0;
+       char *writebuf;
+       struct urb *writeurb;
+       int rv;
+       int transfer_length;
+       ssize_t writecount = 0;
+
+       if (mutex_lock_interruptible(&usblp->wmut)) {
+               rv = -EINTR;
+               goto raise_biglock;
+       }
+       if ((rv = usblp_wwait(usblp, !!(file->f_flags & O_NONBLOCK))) < 0)
+               goto raise_wait;
 
        while (writecount < count) {
-               if (!usblp->wcomplete) {
-                       barrier();
-                       if (file->f_flags & O_NONBLOCK) {
-                               writecount += transfer_length;
-                               return writecount ? writecount : -EAGAIN;
-                       }
-
-                       timeout = USBLP_WRITE_TIMEOUT;
-
-                       rv = wait_event_interruptible_timeout(usblp->wait, usblp->wcomplete || !usblp->present , timeout);
-                       if (rv < 0)
-                               return writecount ? writecount : -EINTR;
-               }
-               intr = mutex_lock_interruptible (&usblp->mut);
-               if (intr)
-                       return writecount ? writecount : -EINTR;
-               if (!usblp->present) {
-                       mutex_unlock (&usblp->mut);
-                       return -ENODEV;
-               }
-
-               if (usblp->sleeping) {
-                       mutex_unlock (&usblp->mut);
-                       return writecount ? writecount : -ENODEV;
-               }
-
-               if (usblp->writeurb->status != 0) {
-                       if (usblp->quirks & USBLP_QUIRK_BIDIR) {
-                               if (!usblp->wcomplete)
-                                       err("usblp%d: error %d writing to printer",
-                                               usblp->minor, usblp->writeurb->status);
-                               err = usblp->writeurb->status;
-                       } else
-                               err = usblp_check_status(usblp, err);
-                       mutex_unlock (&usblp->mut);
-
-                       /* if the fault was due to disconnect, let khubd's
-                        * call to usblp_disconnect() grab usblp->mut ...
-                        */
-                       schedule ();
-                       continue;
-               }
-
-               /* We must increment writecount here, and not at the
-                * end of the loop. Otherwise, the final loop iteration may
-                * be skipped, leading to incomplete printer output.
+               /*
+                * Step 1: Submit next block.
                 */
-               writecount += transfer_length;
-               if (writecount == count) {
-                       mutex_unlock(&usblp->mut);
-                       break;
-               }
-
-               transfer_length=(count - writecount);
-               if (transfer_length > USBLP_BUF_SIZE)
+               if ((transfer_length = count - writecount) > USBLP_BUF_SIZE)
                        transfer_length = USBLP_BUF_SIZE;
 
-               usblp->writeurb->transfer_buffer_length = transfer_length;
-
-               if (copy_from_user(usblp->writeurb->transfer_buffer, 
+               rv = -ENOMEM;
+               if ((writebuf = kmalloc(USBLP_BUF_SIZE, GFP_KERNEL)) == NULL)
+                       goto raise_buf;
+               if ((writeurb = usb_alloc_urb(0, GFP_KERNEL)) == NULL)
+                       goto raise_urb;
+               usb_fill_bulk_urb(writeurb, usblp->dev,
+                       usb_sndbulkpipe(usblp->dev,
+                         usblp->protocol[usblp->current_protocol].epwrite->bEndpointAddress),
+                       writebuf, transfer_length, usblp_bulk_write, usblp);
+               usb_anchor_urb(writeurb, &usblp->urbs);
+
+               if (copy_from_user(writebuf,
                                   buffer + writecount, transfer_length)) {
-                       mutex_unlock(&usblp->mut);
-                       return writecount ? writecount : -EFAULT;
+                       rv = -EFAULT;
+                       goto raise_badaddr;
                }
 
-               usblp->writeurb->dev = usblp->dev;
+               spin_lock_irq(&usblp->lock);
                usblp->wcomplete = 0;
-               err = usb_submit_urb(usblp->writeurb, GFP_KERNEL);
-               if (err) {
+               spin_unlock_irq(&usblp->lock);
+               if ((rv = usb_submit_urb(writeurb, GFP_KERNEL)) < 0) {
+                       usblp->wstatus = 0;
+                       spin_lock_irq(&usblp->lock);
                        usblp->wcomplete = 1;
-                       if (err != -ENOMEM)
-                               count = -EIO;
-                       else
-                               count = writecount ? writecount : -ENOMEM;
-                       mutex_unlock (&usblp->mut);
-                       break;
+                       wake_up(&usblp->wwait);
+                       spin_unlock_irq(&usblp->lock);
+                       if (rv != -ENOMEM)
+                               rv = -EIO;
+                       goto raise_submit;
+               }
+
+               /*
+                * Step 2: Wait for transfer to end, collect results.
+                */
+               rv = usblp_wwait(usblp, !!(file->f_flags&O_NONBLOCK));
+               if (rv < 0) {
+                       /*
+                        * If interrupted, we simply leave the URB to dangle,
+                        * so the ->release will call usb_kill_urb().
+                        */
+                       goto collect_error;
                }
-               mutex_unlock (&usblp->mut);
+
+               if (usblp->wstatus < 0) {
+                       usblp_check_status(usblp, 0);
+                       rv = -EIO;
+                       goto collect_error;
+               }
+               /*
+                * This is critical: it must be our URB, not other writer's.
+                * The wmut exists mainly to cover us here.
+                */
+               writecount += usblp->wstatus;
        }
 
-       return count;
+       mutex_unlock(&usblp->wmut);
+       return writecount;
+
+raise_submit:
+raise_badaddr:
+       usb_unanchor_urb(writeurb);
+       usb_free_urb(writeurb);
+raise_urb:
+       kfree(writebuf);
+raise_buf:
+raise_wait:
+collect_error:         /* Out of raise sequence */
+       mutex_unlock(&usblp->wmut);
+raise_biglock:
+       return writecount ? writecount : rv;
 }
 
-static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+/*
+ * Notice that we fail to restart in a few cases: on EFAULT, on restart
+ * error, etc. This is the historical behaviour. In all such cases we return
+ * EIO, and applications loop in order to get the new read going.
+ */
+static ssize_t usblp_read(struct file *file, char __user *buffer, size_t len, loff_t *ppos)
 {
        struct usblp *usblp = file->private_data;
-       int rv, intr;
+       ssize_t count;
+       ssize_t avail;
+       int rv;
 
        if (!usblp->bidir)
                return -EINVAL;
 
-       intr = mutex_lock_interruptible (&usblp->mut);
-       if (intr)
-               return -EINTR;
-       if (!usblp->present) {
-               count = -ENODEV;
+       rv = usblp_rwait_and_lock(usblp, !!(file->f_flags & O_NONBLOCK));
+       if (rv < 0)
+               return rv;
+
+       if ((avail = usblp->rstatus) < 0) {
+               printk(KERN_ERR "usblp%d: error %d reading from printer\n",
+                   usblp->minor, (int)avail);
+               usblp_submit_read(usblp);
+               count = -EIO;
                goto done;
        }
 
-       if (!usblp->rcomplete) {
-               barrier();
+       count = len < avail - usblp->readcount ? len : avail - usblp->readcount;
+       if (count != 0 &&
+           copy_to_user(buffer, usblp->readbuf + usblp->readcount, count)) {
+               count = -EFAULT;
+               goto done;
+       }
 
-               if (file->f_flags & O_NONBLOCK) {
-                       count = -EAGAIN;
-                       goto done;
-               }
-               mutex_unlock(&usblp->mut);
-               rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present);
-               mutex_lock(&usblp->mut);
-               if (rv < 0) {
-                       count = -EINTR;
+       if ((usblp->readcount += count) == avail) {
+               if (usblp_submit_read(usblp) < 0) {
+                       /* We don't want to leak USB return codes into errno. */
+                       if (count == 0)
+                               count = -EIO;
                        goto done;
                }
        }
 
-       if (!usblp->present) {
-               count = -ENODEV;
-               goto done;
+done:
+       mutex_unlock (&usblp->mut);
+       return count;
+}
+
+/*
+ * Wait for the write path to come idle.
+ * This is called under the ->wmut, so the idle path stays idle.
+ *
+ * Our write path has a peculiar property: it does not buffer like a tty,
+ * but waits for the write to succeed. This allows our ->release to bug out
+ * without waiting for writes to drain. But it obviously does not work
+ * when O_NONBLOCK is set. So, applications setting O_NONBLOCK must use
+ * select(2) or poll(2) to wait for the buffer to drain before closing.
+ * Alternatively, set blocking mode with fcntl and issue a zero-size write.
+ *
+ * Old v0.13 code had a non-functional timeout for wait_event(). Someone forgot
+ * to check the return code for timeout expiration, so it had no effect.
+ * Apparently, it was intended to check for error conditons, such as out
+ * of paper. It is going to return when we settle things with CUPS. XXX
+ */
+static int usblp_wwait(struct usblp *usblp, int nonblock)
+{
+       DECLARE_WAITQUEUE(waita, current);
+       int rc;
+
+       add_wait_queue(&usblp->wwait, &waita);
+       for (;;) {
+               if (mutex_lock_interruptible(&usblp->mut)) {
+                       rc = -EINTR;
+                       break;
+               }
+               set_current_state(TASK_INTERRUPTIBLE);
+               if ((rc = usblp_wtest(usblp, nonblock)) < 0) {
+                       mutex_unlock(&usblp->mut);
+                       break;
+               }
+               mutex_unlock(&usblp->mut);
+               if (rc == 0)
+                       break;
+               schedule();
        }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(&usblp->wwait, &waita);
+       return rc;
+}
 
-       if (usblp->sleeping) {
-               count = -ENODEV;
-               goto done;
+static int usblp_wtest(struct usblp *usblp, int nonblock)
+{
+       unsigned long flags;
+
+       if (!usblp->present)
+               return -ENODEV;
+       if (signal_pending(current))
+               return -EINTR;
+       spin_lock_irqsave(&usblp->lock, flags);
+       if (usblp->wcomplete) {
+               spin_unlock_irqrestore(&usblp->lock, flags);
+               return 0;
        }
+       spin_unlock_irqrestore(&usblp->lock, flags);
+       if (usblp->sleeping)
+               return -ENODEV;
+       if (nonblock)
+               return -EAGAIN;
+       return 1;
+}
 
-       if (usblp->readurb->status) {
-               err("usblp%d: error %d reading from printer",
-                       usblp->minor, usblp->readurb->status);
-               usblp->readurb->dev = usblp->dev;
-               usblp->readcount = 0;
-               usblp->rcomplete = 0;
-               if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0)
-                       dbg("error submitting urb");
-               count = -EIO;
-               goto done;
+/*
+ * Wait for read bytes to become available. This probably should have been
+ * called usblp_r_lock_and_wait(), because we lock first. But it's a traditional
+ * name for functions which lock and return.
+ *
+ * We do not use wait_event_interruptible because it makes locking iffy.
+ */
+static int usblp_rwait_and_lock(struct usblp *usblp, int nonblock)
+{
+       DECLARE_WAITQUEUE(waita, current);
+       int rc;
+
+       add_wait_queue(&usblp->rwait, &waita);
+       for (;;) {
+               if (mutex_lock_interruptible(&usblp->mut)) {
+                       rc = -EINTR;
+                       break;
+               }
+               set_current_state(TASK_INTERRUPTIBLE);
+               if ((rc = usblp_rtest(usblp, nonblock)) < 0) {
+                       mutex_unlock(&usblp->mut);
+                       break;
+               }
+               if (rc == 0)    /* Keep it locked */
+                       break;
+               mutex_unlock(&usblp->mut);
+               schedule();
        }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(&usblp->rwait, &waita);
+       return rc;
+}
 
-       count = count < usblp->readurb->actual_length - usblp->readcount ?
-               count : usblp->readurb->actual_length - usblp->readcount;
+static int usblp_rtest(struct usblp *usblp, int nonblock)
+{
+       unsigned long flags;
 
-       if (copy_to_user(buffer, usblp->readurb->transfer_buffer + usblp->readcount, count)) {
-               count = -EFAULT;
-               goto done;
+       if (!usblp->present)
+               return -ENODEV;
+       if (signal_pending(current))
+               return -EINTR;
+       spin_lock_irqsave(&usblp->lock, flags);
+       if (usblp->rcomplete) {
+               spin_unlock_irqrestore(&usblp->lock, flags);
+               return 0;
        }
+       spin_unlock_irqrestore(&usblp->lock, flags);
+       if (usblp->sleeping)
+               return -ENODEV;
+       if (nonblock)
+               return -EAGAIN;
+       return 1;
+}
 
-       if ((usblp->readcount += count) == usblp->readurb->actual_length) {
-               usblp->readcount = 0;
-               usblp->readurb->dev = usblp->dev;
-               usblp->rcomplete = 0;
-               if (usb_submit_urb(usblp->readurb, GFP_KERNEL)) {
-                       count = -EIO;
-                       goto done;
-               }
+/*
+ * Please check ->bidir and other such things outside for now.
+ */
+static int usblp_submit_read(struct usblp *usblp)
+{
+       struct urb *urb;
+       unsigned long flags;
+       int rc;
+
+       rc = -ENOMEM;
+       if ((urb = usb_alloc_urb(0, GFP_KERNEL)) == NULL)
+               goto raise_urb;
+
+       usb_fill_bulk_urb(urb, usblp->dev,
+               usb_rcvbulkpipe(usblp->dev,
+                 usblp->protocol[usblp->current_protocol].epread->bEndpointAddress),
+               usblp->readbuf, USBLP_BUF_SIZE_IN,
+               usblp_bulk_read, usblp);
+       usb_anchor_urb(urb, &usblp->urbs);
+
+       spin_lock_irqsave(&usblp->lock, flags);
+       usblp->readcount = 0; /* XXX Why here? */
+       usblp->rcomplete = 0;
+       spin_unlock_irqrestore(&usblp->lock, flags);
+       if ((rc = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
+               dbg("error submitting urb (%d)", rc);
+               spin_lock_irqsave(&usblp->lock, flags);
+               usblp->rstatus = rc;
+               usblp->rcomplete = 1;
+               spin_unlock_irqrestore(&usblp->lock, flags);
+               goto raise_submit;
        }
 
-done:
-       mutex_unlock (&usblp->mut);
-       return count;
+       return 0;
+
+raise_submit:
+       usb_unanchor_urb(urb);
+       usb_free_urb(urb);
+raise_urb:
+       return rc;
 }
 
 /*
@@ -891,55 +1055,41 @@ static int usblp_probe(struct usb_interface *intf,
        /* Malloc and start initializing usblp structure so we can use it
         * directly. */
        if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) {
-               err("out of memory for usblp");
+               retval = -ENOMEM;
                goto abort;
        }
        usblp->dev = dev;
+       mutex_init(&usblp->wmut);
        mutex_init (&usblp->mut);
-       init_waitqueue_head(&usblp->wait);
+       spin_lock_init(&usblp->lock);
+       init_waitqueue_head(&usblp->rwait);
+       init_waitqueue_head(&usblp->wwait);
+       init_usb_anchor(&usblp->urbs);
        usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
        usblp->intf = intf;
 
-       usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!usblp->writeurb) {
-               err("out of memory");
-               goto abort;
-       }
-       usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!usblp->readurb) {
-               err("out of memory");
-               goto abort;
-       }
-
        /* Malloc device ID string buffer to the largest expected length,
         * since we can re-query it on an ioctl and a dynamic string
         * could change in length. */
        if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) {
-               err("out of memory for device_id_string");
+               retval = -ENOMEM;
                goto abort;
        }
 
-       usblp->writebuf = usblp->readbuf = NULL;
-       usblp->writeurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-       usblp->readurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-       /* Malloc write & read buffers.  We somewhat wastefully
+       /*
+        * Allocate read buffer. We somewhat wastefully
         * malloc both regardless of bidirectionality, because the
-        * alternate setting can be changed later via an ioctl. */
-       if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
-                               GFP_KERNEL, &usblp->writeurb->transfer_dma))) {
-               err("out of memory for write buf");
-               goto abort;
-       }
-       if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
-                               GFP_KERNEL, &usblp->readurb->transfer_dma))) {
-               err("out of memory for read buf");
+        * alternate setting can be changed later via an ioctl.
+        */
+       if (!(usblp->readbuf = kmalloc(USBLP_BUF_SIZE_IN, GFP_KERNEL))) {
+               retval = -ENOMEM;
                goto abort;
        }
 
        /* Allocate buffer for printer status */
        usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL);
        if (!usblp->statusbuf) {
-               err("out of memory for statusbuf");
+               retval = -ENOMEM;
                goto abort;
        }
 
@@ -954,12 +1104,15 @@ static int usblp_probe(struct usb_interface *intf,
                dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
                        le16_to_cpu(dev->descriptor.idVendor),
                        le16_to_cpu(dev->descriptor.idProduct));
+               retval = -ENODEV;
                goto abort;
        }
 
        /* Setup the selected alternate setting and endpoints. */
-       if (usblp_set_protocol(usblp, protocol) < 0)
+       if (usblp_set_protocol(usblp, protocol) < 0) {
+               retval = -ENODEV;       /* ->probe isn't ->ioctl */
                goto abort;
+       }
 
        /* Retrieve and store the device ID string. */
        usblp_cache_device_id_string(usblp);
@@ -977,12 +1130,14 @@ static int usblp_probe(struct usb_interface *intf,
 
        retval = usb_register_dev(intf, &usblp_class);
        if (retval) {
-               err("Not able to get a minor for this device.");
+               printk(KERN_ERR "usblp: Not able to get a minor"
+                   " (base %u, slice default): %d\n",
+                   USBLP_MINOR_BASE, retval);
                goto abort_intfdata;
        }
        usblp->minor = intf->minor;
-       info("usblp%d: USB %sdirectional printer dev %d "
-               "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
+       printk(KERN_INFO "usblp%d: USB %sdirectional printer dev %d "
+               "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X\n",
                usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
                usblp->ifnum,
                usblp->protocol[usblp->current_protocol].alt_setting,
@@ -997,19 +1152,12 @@ abort_intfdata:
        device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
 abort:
        if (usblp) {
-               if (usblp->writebuf)
-                       usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-                               usblp->writebuf, usblp->writeurb->transfer_dma);
-               if (usblp->readbuf)
-                       usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-                               usblp->readbuf, usblp->readurb->transfer_dma);
+               kfree(usblp->readbuf);
                kfree(usblp->statusbuf);
                kfree(usblp->device_id_string);
-               usb_free_urb(usblp->writeurb);
-               usb_free_urb(usblp->readurb);
                kfree(usblp);
        }
-       return -EIO;
+       return retval;
 }
 
 /*
@@ -1078,8 +1226,9 @@ static int usblp_select_alts(struct usblp *usblp)
                if (ifd->desc.bInterfaceProtocol == 1) {
                        epread = NULL;
                } else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
-                       info("Disabling reads from problem bidirectional "
-                               "printer on usblp%d", usblp->minor);
+                       printk(KERN_INFO "usblp%d: Disabling reads from "
+                           "problematic bidirectional printer\n",
+                           usblp->minor);
                        epread = NULL;
                }
 
@@ -1119,25 +1268,12 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol)
                return -EINVAL;
        r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
        if (r < 0) {
-               err("can't set desired altsetting %d on interface %d",
+               printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n",
                        alts, usblp->ifnum);
                return r;
        }
 
-       usb_fill_bulk_urb(usblp->writeurb, usblp->dev,
-               usb_sndbulkpipe(usblp->dev,
-                 usblp->protocol[protocol].epwrite->bEndpointAddress),
-               usblp->writebuf, 0,
-               usblp_bulk_write, usblp);
-
        usblp->bidir = (usblp->protocol[protocol].epread != NULL);
-       if (usblp->bidir)
-               usb_fill_bulk_urb(usblp->readurb, usblp->dev,
-                       usb_rcvbulkpipe(usblp->dev,
-                         usblp->protocol[protocol].epread->bEndpointAddress),
-                       usblp->readbuf, USBLP_BUF_SIZE,
-                       usblp_bulk_read, usblp);
-
        usblp->current_protocol = protocol;
        dbg("usblp%d set protocol %d", usblp->minor, protocol);
        return 0;
@@ -1190,13 +1326,11 @@ static void usblp_disconnect(struct usb_interface *intf)
        mutex_lock (&usblp_mutex);
        mutex_lock (&usblp->mut);
        usblp->present = 0;
+       wake_up(&usblp->wwait);
+       wake_up(&usblp->rwait);
        usb_set_intfdata (intf, NULL);
 
        usblp_unlink_urbs(usblp);
-       usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-                       usblp->writebuf, usblp->writeurb->transfer_dma);
-       usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-                       usblp->readbuf, usblp->readurb->transfer_dma);
        mutex_unlock (&usblp->mut);
 
        if (!usblp->used)
@@ -1211,6 +1345,11 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message)
        /* we take no more IO */
        usblp->sleeping = 1;
        usblp_unlink_urbs(usblp);
+#if 0 /* XXX Do we want this? What if someone is reading, should we fail? */
+       /* not strictly necessary, but just in case */
+       wake_up(&usblp->wwait);
+       wake_up(&usblp->rwait);
+#endif
 
        return 0;
 }
@@ -1251,12 +1390,7 @@ static struct usb_driver usblp_driver = {
 
 static int __init usblp_init(void)
 {
-       int retval;
-       retval = usb_register(&usblp_driver);
-       if (!retval)
-               info(DRIVER_VERSION ": " DRIVER_DESC);
-
-       return retval;
+       return usb_register(&usblp_driver);
 }
 
 static void __exit usblp_exit(void)
index 346fc030c929ae172b6658df8f1a2b54113e1ac3..97b09f282705bb4c4249e733d89ea3ca43876cd2 100644 (file)
@@ -86,6 +86,31 @@ config USB_SUSPEND
 
          If you are unsure about this, say N here.
 
+config USB_PERSIST
+       bool "USB device persistence during system suspend (DANGEROUS)"
+       depends on USB && PM && EXPERIMENTAL
+       default n
+       help
+
+         If you say Y here and enable the "power/persist" attribute
+         for a USB device, the device's data structures will remain
+         persistent across system suspend, even if the USB bus loses
+         power.  (This includes hibernation, also known as swsusp or
+         suspend-to-disk.)  The devices will reappear as if by magic
+         when the system wakes up, with no need to unmount USB
+         filesystems, rmmod host-controller drivers, or do anything
+         else.
+
+               WARNING: This option can be dangerous!
+
+         If a USB device is replaced by another of the same type while
+         the system is asleep, there's a good chance the kernel won't
+         detect the change.  Likewise if the media in a USB storage
+         device is replaced.  When this happens it's almost certain to
+         cause data corruption and maybe even crash your system.
+
+         If you are unsure, say N here.
+
 config USB_OTG
        bool
        depends on USB && EXPERIMENTAL
index dd3482328ad2603e7726e10d07dd4f2dc09ffc58..cb69aa1e02e8762913e1d68901fb64495b68d8d0 100644 (file)
@@ -85,15 +85,21 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
        memcpy(&endpoint->desc, d, n);
        INIT_LIST_HEAD(&endpoint->urb_list);
 
-       /* If the bInterval value is outside the legal range,
-        * set it to a default value: 32 ms */
+       /* Fix up bInterval values outside the legal range. Use 32 ms if no
+        * proper value can be guessed. */
        i = 0;          /* i = min, j = max, n = default */
        j = 255;
        if (usb_endpoint_xfer_int(d)) {
                i = 1;
                switch (to_usb_device(ddev)->speed) {
                case USB_SPEED_HIGH:
-                       n = 9;          /* 32 ms = 2^(9-1) uframes */
+                       /* Many device manufacturers are using full-speed
+                        * bInterval values in high-speed interrupt endpoint
+                        * descriptors. Try to fix those and fall back to a
+                        * 32 ms default value otherwise. */
+                       n = fls(d->bInterval*8);
+                       if (n == 0)
+                               n = 9;  /* 32 ms = 2^(9-1) uframes */
                        j = 16;
                        break;
                default:                /* USB_SPEED_FULL or _LOW */
@@ -124,6 +130,21 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
                endpoint->desc.bInterval = n;
        }
 
+       /* Some buggy low-speed devices have Bulk endpoints, which is
+        * explicitly forbidden by the USB spec.  In an attempt to make
+        * them usable, we will try treating them as Interrupt endpoints.
+        */
+       if (to_usb_device(ddev)->speed == USB_SPEED_LOW &&
+                       usb_endpoint_xfer_bulk(d)) {
+               dev_warn(ddev, "config %d interface %d altsetting %d "
+                   "endpoint 0x%X is Bulk; changing to Interrupt\n",
+                   cfgno, inum, asnum, d->bEndpointAddress);
+               endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT;
+               endpoint->desc.bInterval = 1;
+               if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8)
+                       endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
+       }
+
        /* Skip over any Class Specific or Vendor Specific descriptors;
         * find the next endpoint or interface descriptor */
        endpoint->extra = buffer;
@@ -274,6 +295,7 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
        struct usb_descriptor_header *header;
        int len, retval;
        u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
+       unsigned iad_num = 0;
 
        memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
        if (config->desc.bDescriptorType != USB_DT_CONFIG ||
@@ -351,6 +373,20 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
                                ++n;
                        }
 
+               } else if (header->bDescriptorType ==
+                               USB_DT_INTERFACE_ASSOCIATION) {
+                       if (iad_num == USB_MAXIADS) {
+                               dev_warn(ddev, "found more Interface "
+                                              "Association Descriptors "
+                                              "than allocated for in "
+                                              "configuration %d\n", cfgno);
+                       } else {
+                               config->intf_assoc[iad_num] =
+                                       (struct usb_interface_assoc_descriptor
+                                       *)header;
+                               iad_num++;
+                       }
+
                } else if (header->bDescriptorType == USB_DT_DEVICE ||
                            header->bDescriptorType == USB_DT_CONFIG)
                        dev_warn(ddev, "config %d contains an unexpected "
index 6753ca059ee43808fbbeb0128d27ae54ab56687c..87c794d60aa021ee3b6f1108e2cef34fb519f4c4 100644 (file)
@@ -102,6 +102,10 @@ static const char *format_config =
 /* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
   "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
   
+static const char *format_iad =
+/* A:  FirstIf#=dd IfCount=dd Cls=xx(sssss) Sub=xx Prot=xx */
+  "A:  FirstIf#=%2d IfCount=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n";
+
 static const char *format_iface =
 /* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
   "I:%c If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
@@ -146,6 +150,7 @@ static const struct class_info clas_info[] =
        {USB_CLASS_STILL_IMAGE,         "still"},
        {USB_CLASS_CSCID,               "scard"},
        {USB_CLASS_CONTENT_SEC,         "c-sec"},
+       {USB_CLASS_VIDEO,               "video"},
        {-1,                            "unk."}         /* leave as last */
 };
 
@@ -286,6 +291,21 @@ static char *usb_dump_interface(
        return start;
 }
 
+static char *usb_dump_iad_descriptor(char *start, char *end,
+       const struct usb_interface_assoc_descriptor *iad)
+{
+       if (start > end)
+               return start;
+       start += sprintf(start, format_iad,
+                        iad->bFirstInterface,
+                        iad->bInterfaceCount,
+                        iad->bFunctionClass,
+                        class_decode(iad->bFunctionClass),
+                        iad->bFunctionSubClass,
+                        iad->bFunctionProtocol);
+       return start;
+}
+
 /* TBD:
  * 0. TBDs
  * 1. marking active interface altsettings (code lists all, but should mark
@@ -322,6 +342,12 @@ static char *usb_dump_config (
        if (!config)            /* getting these some in 2.3.7; none in 2.3.6 */
                return start + sprintf(start, "(null Cfg. desc.)\n");
        start = usb_dump_config_descriptor(start, end, &config->desc, active);
+       for (i = 0; i < USB_MAXIADS; i++) {
+               if (config->intf_assoc[i] == NULL)
+                       break;
+               start = usb_dump_iad_descriptor(start, end,
+                                       config->intf_assoc[i]);
+       }
        for (i = 0; i < config->desc.bNumInterfaces; i++) {
                intfc = config->intf_cache[i];
                interface = config->interface[i];
index 2619986e53000f95667365157193dd1dec0d3453..73c49362cd47c7d593e815d7bd3f9f194d899ff3 100644 (file)
 
 #include <linux/device.h>
 #include <linux/usb.h>
+#include <linux/usb/quirks.h>
 #include <linux/workqueue.h>
 #include "hcd.h"
 #include "usb.h"
 
+#define VERBOSE_DEBUG  0
+
+#if VERBOSE_DEBUG
+#define dev_vdbg       dev_dbg
+#else
+#define dev_vdbg(dev, fmt, args...)    do { } while (0)
+#endif
+
 #ifdef CONFIG_HOTPLUG
 
 /*
@@ -802,18 +811,17 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
                        udev->state == USB_STATE_SUSPENDED)
                goto done;
 
-       /* For devices that don't have a driver, we do a standard suspend. */
-       if (udev->dev.driver == NULL) {
+       /* For devices that don't have a driver, we do a generic suspend. */
+       if (udev->dev.driver)
+               udriver = to_usb_device_driver(udev->dev.driver);
+       else {
                udev->do_remote_wakeup = 0;
-               status = usb_port_suspend(udev);
-               goto done;
+               udriver = &usb_generic_driver;
        }
-
-       udriver = to_usb_device_driver(udev->dev.driver);
        status = udriver->suspend(udev, msg);
 
-done:
-       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ done:
+       dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
        if (status == 0)
                udev->dev.power.power_state.event = msg.event;
        return status;
@@ -825,8 +833,9 @@ static int usb_resume_device(struct usb_device *udev)
        struct usb_device_driver        *udriver;
        int                             status = 0;
 
-       if (udev->state == USB_STATE_NOTATTACHED ||
-                       udev->state != USB_STATE_SUSPENDED)
+       if (udev->state == USB_STATE_NOTATTACHED)
+               goto done;
+       if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume)
                goto done;
 
        /* Can't resume it if it doesn't have a driver. */
@@ -835,11 +844,14 @@ static int usb_resume_device(struct usb_device *udev)
                goto done;
        }
 
+       if (udev->quirks & USB_QUIRK_RESET_RESUME)
+               udev->reset_resume = 1;
+
        udriver = to_usb_device_driver(udev->dev.driver);
        status = udriver->resume(udev);
 
-done:
-       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ done:
+       dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
        if (status == 0) {
                udev->autoresume_disabled = 0;
                udev->dev.power.power_state.event = PM_EVENT_ON;
@@ -877,15 +889,13 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
                mark_quiesced(intf);
        }
 
-done:
-       // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
-       if (status == 0)
-               intf->dev.power.power_state.event = msg.event;
+ done:
+       dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
        return status;
 }
 
 /* Caller has locked intf's usb_device's pm_mutex */
-static int usb_resume_interface(struct usb_interface *intf)
+static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
 {
        struct usb_driver       *driver;
        int                     status = 0;
@@ -905,23 +915,37 @@ static int usb_resume_interface(struct usb_interface *intf)
        }
        driver = to_usb_driver(intf->dev.driver);
 
-       if (driver->resume) {
-               status = driver->resume(intf);
-               if (status)
-                       dev_err(&intf->dev, "%s error %d\n",
-                                       "resume", status);
-               else
-                       mark_active(intf);
+       if (reset_resume) {
+               if (driver->reset_resume) {
+                       status = driver->reset_resume(intf);
+                       if (status)
+                               dev_err(&intf->dev, "%s error %d\n",
+                                               "reset_resume", status);
+               } else {
+                       // status = -EOPNOTSUPP;
+                       dev_warn(&intf->dev, "no %s for driver %s?\n",
+                                       "reset_resume", driver->name);
+               }
        } else {
-               dev_warn(&intf->dev, "no resume for driver %s?\n",
-                               driver->name);
-               mark_active(intf);
+               if (driver->resume) {
+                       status = driver->resume(intf);
+                       if (status)
+                               dev_err(&intf->dev, "%s error %d\n",
+                                               "resume", status);
+               } else {
+                       // status = -EOPNOTSUPP;
+                       dev_warn(&intf->dev, "no %s for driver %s?\n",
+                                       "resume", driver->name);
+               }
        }
 
 done:
-       // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+       dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
        if (status == 0)
-               intf->dev.power.power_state.event = PM_EVENT_ON;
+               mark_active(intf);
+
+       /* FIXME: Unbind the driver and reprobe if the resume failed
+        * (not possible if auto_pm is set) */
        return status;
 }
 
@@ -958,6 +982,18 @@ static int autosuspend_check(struct usb_device *udev)
                                                "for autosuspend\n");
                                return -EOPNOTSUPP;
                        }
+
+                       /* Don't allow autosuspend if the device will need
+                        * a reset-resume and any of its interface drivers
+                        * doesn't include support.
+                        */
+                       if (udev->quirks & USB_QUIRK_RESET_RESUME) {
+                               struct usb_driver *driver;
+
+                               driver = to_usb_driver(intf->dev.driver);
+                               if (!driver->reset_resume)
+                                       return -EOPNOTSUPP;
+                       }
                }
        }
 
@@ -974,7 +1010,7 @@ static int autosuspend_check(struct usb_device *udev)
                         * or for the past.
                         */
                        queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-                                       suspend_time - jiffies);
+                               round_jiffies_relative(suspend_time - jiffies));
                        }
                return -EAGAIN;
        }
@@ -1054,14 +1090,21 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
                                break;
                }
        }
-       if (status == 0)
+       if (status == 0) {
+
+               /* Non-root devices don't need to do anything for FREEZE
+                * or PRETHAW. */
+               if (udev->parent && (msg.event == PM_EVENT_FREEZE ||
+                               msg.event == PM_EVENT_PRETHAW))
+                       goto done;
                status = usb_suspend_device(udev, msg);
+       }
 
        /* If the suspend failed, resume interfaces that did get suspended */
        if (status != 0) {
                while (--i >= 0) {
                        intf = udev->actconfig->interface[i];
-                       usb_resume_interface(intf);
+                       usb_resume_interface(intf, 0);
                }
 
                /* Try another autosuspend when the interfaces aren't busy */
@@ -1076,7 +1119,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
        }
 
  done:
-       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
        return status;
 }
 
@@ -1131,7 +1174,8 @@ static int usb_resume_both(struct usb_device *udev)
                        status = usb_autoresume_device(parent);
                        if (status == 0) {
                                status = usb_resume_device(udev);
-                               if (status) {
+                               if (status || udev->state ==
+                                               USB_STATE_NOTATTACHED) {
                                        usb_autosuspend_device(parent);
 
                                        /* It's possible usb_resume_device()
@@ -1152,28 +1196,25 @@ static int usb_resume_both(struct usb_device *udev)
                        /* We can't progagate beyond the USB subsystem,
                         * so if a root hub's controller is suspended
                         * then we're stuck. */
-                       if (udev->dev.parent->power.power_state.event !=
-                                       PM_EVENT_ON)
-                               status = -EHOSTUNREACH;
-                       else
-                               status = usb_resume_device(udev);
+                       status = usb_resume_device(udev);
                }
        } else {
 
-               /* Needed only for setting udev->dev.power.power_state.event
-                * and for possible debugging message. */
+               /* Needed for setting udev->dev.power.power_state.event,
+                * for possible debugging message, and for reset_resume. */
                status = usb_resume_device(udev);
        }
 
        if (status == 0 && udev->actconfig) {
                for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
                        intf = udev->actconfig->interface[i];
-                       usb_resume_interface(intf);
+                       usb_resume_interface(intf, udev->reset_resume);
                }
        }
 
  done:
-       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       udev->reset_resume = 0;
        return status;
 }
 
@@ -1240,8 +1281,8 @@ void usb_autosuspend_device(struct usb_device *udev)
        int     status;
 
        status = usb_autopm_do_device(udev, -1);
-       // dev_dbg(&udev->dev, "%s: cnt %d\n",
-       //              __FUNCTION__, udev->pm_usage_cnt);
+       dev_vdbg(&udev->dev, "%s: cnt %d\n",
+                       __FUNCTION__, udev->pm_usage_cnt);
 }
 
 /**
@@ -1260,8 +1301,8 @@ void usb_autosuspend_device(struct usb_device *udev)
 void usb_try_autosuspend_device(struct usb_device *udev)
 {
        usb_autopm_do_device(udev, 0);
-       // dev_dbg(&udev->dev, "%s: cnt %d\n",
-       //              __FUNCTION__, udev->pm_usage_cnt);
+       dev_vdbg(&udev->dev, "%s: cnt %d\n",
+                       __FUNCTION__, udev->pm_usage_cnt);
 }
 
 /**
@@ -1288,8 +1329,8 @@ int usb_autoresume_device(struct usb_device *udev)
        int     status;
 
        status = usb_autopm_do_device(udev, 1);
-       // dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
-       //              __FUNCTION__, status, udev->pm_usage_cnt);
+       dev_vdbg(&udev->dev, "%s: status %d cnt %d\n",
+                       __FUNCTION__, status, udev->pm_usage_cnt);
        return status;
 }
 
@@ -1361,8 +1402,8 @@ void usb_autopm_put_interface(struct usb_interface *intf)
        int     status;
 
        status = usb_autopm_do_interface(intf, -1);
-       // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
-       //              __FUNCTION__, status, intf->pm_usage_cnt);
+       dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+                       __FUNCTION__, status, intf->pm_usage_cnt);
 }
 EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
 
@@ -1405,8 +1446,8 @@ int usb_autopm_get_interface(struct usb_interface *intf)
        int     status;
 
        status = usb_autopm_do_interface(intf, 1);
-       // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
-       //              __FUNCTION__, status, intf->pm_usage_cnt);
+       dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+                       __FUNCTION__, status, intf->pm_usage_cnt);
        return status;
 }
 EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
@@ -1427,8 +1468,8 @@ int usb_autopm_set_interface(struct usb_interface *intf)
        int     status;
 
        status = usb_autopm_do_interface(intf, 0);
-       // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
-       //              __FUNCTION__, status, intf->pm_usage_cnt);
+       dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+                       __FUNCTION__, status, intf->pm_usage_cnt);
        return status;
 }
 EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
@@ -1508,8 +1549,15 @@ static int usb_resume(struct device *dev)
        if (!is_usb_device(dev))        /* Ignore PM for interfaces */
                return 0;
        udev = to_usb_device(dev);
-       if (udev->autoresume_disabled)
-               return -EPERM;
+
+       /* If autoresume is disabled then we also want to prevent resume
+        * during system wakeup.  However, a "persistent-device" reset-resume
+        * after power loss counts as a wakeup event.  So allow a
+        * reset-resume to occur if remote wakeup is enabled. */
+       if (udev->autoresume_disabled) {
+               if (!(udev->reset_resume && udev->do_remote_wakeup))
+                       return -EPERM;
+       }
        return usb_external_resume_device(udev);
 }
 
index 01c857ac27afc09eed98c1a190d794073b73c470..5d860bc9b42143f6729a9df40521ec42943b21b1 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/spinlock.h>
 #include <linux/errno.h>
+#include <linux/rwsem.h>
 #include <linux/usb.h>
 
 #include "usb.h"
 
 #define MAX_USB_MINORS 256
 static const struct file_operations *usb_minors[MAX_USB_MINORS];
-static DEFINE_SPINLOCK(minor_lock);
+static DECLARE_RWSEM(minor_rwsem);
 
 static int usb_open(struct inode * inode, struct file * file)
 {
@@ -33,14 +33,11 @@ static int usb_open(struct inode * inode, struct file * file)
        int err = -ENODEV;
        const struct file_operations *old_fops, *new_fops = NULL;
 
-       spin_lock (&minor_lock);
+       down_read(&minor_rwsem);
        c = usb_minors[minor];
 
-       if (!c || !(new_fops = fops_get(c))) {
-               spin_unlock(&minor_lock);
-               return err;
-       }
-       spin_unlock(&minor_lock);
+       if (!c || !(new_fops = fops_get(c)))
+               goto done;
 
        old_fops = file->f_op;
        file->f_op = new_fops;
@@ -52,6 +49,8 @@ static int usb_open(struct inode * inode, struct file * file)
                file->f_op = fops_get(old_fops);
        }
        fops_put(old_fops);
+ done:
+       up_read(&minor_rwsem);
        return err;
 }
 
@@ -166,7 +165,7 @@ int usb_register_dev(struct usb_interface *intf,
        if (class_driver->fops == NULL)
                goto exit;
 
-       spin_lock (&minor_lock);
+       down_write(&minor_rwsem);
        for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
                if (usb_minors[minor])
                        continue;
@@ -176,7 +175,7 @@ int usb_register_dev(struct usb_interface *intf,
                retval = 0;
                break;
        }
-       spin_unlock (&minor_lock);
+       up_write(&minor_rwsem);
 
        if (retval)
                goto exit;
@@ -197,9 +196,9 @@ int usb_register_dev(struct usb_interface *intf,
        intf->usb_dev = device_create(usb_class->class, &intf->dev,
                                      MKDEV(USB_MAJOR, minor), "%s", temp);
        if (IS_ERR(intf->usb_dev)) {
-               spin_lock (&minor_lock);
+               down_write(&minor_rwsem);
                usb_minors[intf->minor] = NULL;
-               spin_unlock (&minor_lock);
+               up_write(&minor_rwsem);
                retval = PTR_ERR(intf->usb_dev);
        }
 exit:
@@ -236,9 +235,9 @@ void usb_deregister_dev(struct usb_interface *intf,
 
        dbg ("removing %d minor", intf->minor);
 
-       spin_lock (&minor_lock);
+       down_write(&minor_rwsem);
        usb_minors[intf->minor] = NULL;
-       spin_unlock (&minor_lock);
+       up_write(&minor_rwsem);
 
        snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
        device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
@@ -247,5 +246,3 @@ void usb_deregister_dev(struct usb_interface *intf,
        destroy_usb_class();
 }
 EXPORT_SYMBOL(usb_deregister_dev);
-
-
index 9bbcb20e2d94c3bf5ca96f77d0c1050d87d14eb2..b2fc2b115256633a2f19bfd2a013ffaffedcaf28 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/usb.h>
 #include "usb.h"
+#include "hcd.h"
 
 static inline const char *plural(int n)
 {
@@ -193,16 +194,34 @@ static void generic_disconnect(struct usb_device *udev)
 
 static int generic_suspend(struct usb_device *udev, pm_message_t msg)
 {
-       /* USB devices enter SUSPEND state through their hubs, but can be
-        * marked for FREEZE as soon as their children are already idled.
-        * But those semantics are useless, so we equate the two (sigh).
+       int rc;
+
+       /* Normal USB devices suspend through their upstream port.
+        * Root hubs don't have upstream ports to suspend,
+        * so we have to shut down their downstream HC-to-USB
+        * interfaces manually by doing a bus (or "global") suspend.
         */
-       return usb_port_suspend(udev);
+       if (!udev->parent)
+               rc = hcd_bus_suspend(udev);
+       else
+               rc = usb_port_suspend(udev);
+       return rc;
 }
 
 static int generic_resume(struct usb_device *udev)
 {
-       return usb_port_resume(udev);
+       int rc;
+
+       /* Normal USB devices resume/reset through their upstream port.
+        * Root hubs don't have upstream ports to resume or reset,
+        * so we have to start up their downstream HC-to-USB
+        * interfaces manually by doing a bus (or "global") resume.
+        */
+       if (!udev->parent)
+               rc = hcd_bus_resume(udev);
+       else
+               rc = usb_port_resume(udev);
+       return rc;
 }
 
 #endif /* CONFIG_PM */
index edf4300a3f7a75d748776ab3fe3d69fbf1a6f66d..5cf6d5f9acbdb749340b0f8922f5ec177afbe3f5 100644 (file)
@@ -207,7 +207,8 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
         * We must ignore the FREEZE vs SUSPEND distinction here, because
         * otherwise the swsusp will save (and restore) garbage state.
         */
-       if (hcd->self.root_hub->dev.power.power_state.event == PM_EVENT_ON)
+       if (!(hcd->state == HC_STATE_SUSPENDED ||
+                       hcd->state == HC_STATE_HALT))
                return -EBUSY;
 
        if (hcd->driver->suspend) {
index 8969e42434b9ca2a2b2a54ea9c7aab0bcccd642a..963520fbef9061db3a42f12d624840bab9976e92 100644 (file)
@@ -582,10 +582,12 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
        }
 
        /* The USB 2.0 spec says 256 ms.  This is close enough and won't
-        * exceed that limit if HZ is 100. */
+        * exceed that limit if HZ is 100. The math is more clunky than
+        * maybe expected, this is to make sure that all timers for USB devices
+        * fire at the same time to give the CPU a break inbetween */
        if (hcd->uses_new_polling ? hcd->poll_rh :
                        (length == 0 && hcd->status_urb != NULL))
-               mod_timer (&hcd->rh_timer, jiffies + msecs_to_jiffies(250));
+               mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
 }
 EXPORT_SYMBOL_GPL(usb_hcd_poll_rh_status);
 
@@ -614,8 +616,8 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)
                urb->hcpriv = hcd;      /* indicate it's queued */
 
                if (!hcd->uses_new_polling)
-                       mod_timer (&hcd->rh_timer, jiffies +
-                                       msecs_to_jiffies(250));
+                       mod_timer (&hcd->rh_timer,
+                               (jiffies/(HZ/4) + 1) * (HZ/4));
 
                /* If a status change has already occurred, report it ASAP */
                else if (hcd->poll_pending)
@@ -901,17 +903,32 @@ EXPORT_SYMBOL (usb_calc_bus_time);
 
 /*-------------------------------------------------------------------------*/
 
-static void urb_unlink (struct urb *urb)
+static void urb_unlink(struct usb_hcd *hcd, struct urb *urb)
 {
        unsigned long           flags;
+       int at_root_hub = (urb->dev == hcd->self.root_hub);
 
        /* clear all state linking urb to this dev (and hcd) */
-
        spin_lock_irqsave (&hcd_data_lock, flags);
        list_del_init (&urb->urb_list);
        spin_unlock_irqrestore (&hcd_data_lock, flags);
-}
 
+       if (hcd->self.uses_dma && !at_root_hub) {
+               if (usb_pipecontrol (urb->pipe)
+                       && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+                       dma_unmap_single (hcd->self.controller, urb->setup_dma,
+                                       sizeof (struct usb_ctrlrequest),
+                                       DMA_TO_DEVICE);
+               if (urb->transfer_buffer_length != 0
+                       && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+                       dma_unmap_single (hcd->self.controller,
+                                       urb->transfer_dma,
+                                       urb->transfer_buffer_length,
+                                       usb_pipein (urb->pipe)
+                                           ? DMA_FROM_DEVICE
+                                           : DMA_TO_DEVICE);
+       }
+}
 
 /* may be called in any context with a valid urb->dev usecount
  * caller surrenders "ownership" of urb
@@ -948,19 +965,9 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
        else switch (hcd->state) {
        case HC_STATE_RUNNING:
        case HC_STATE_RESUMING:
-doit:
                list_add_tail (&urb->urb_list, &ep->urb_list);
                status = 0;
                break;
-       case HC_STATE_SUSPENDED:
-               /* HC upstream links (register access, wakeup signaling) can work
-                * even when the downstream links (and DMA etc) are quiesced; let
-                * usbcore talk to the root hub.
-                */
-               if (hcd->self.controller->power.power_state.event == PM_EVENT_ON
-                               && urb->dev->parent == NULL)
-                       goto doit;
-               /* FALL THROUGH */
        default:
                status = -ESHUTDOWN;
                break;
@@ -1014,7 +1021,7 @@ doit:
        status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
 done:
        if (unlikely (status)) {
-               urb_unlink (urb);
+               urb_unlink(hcd, urb);
                atomic_dec (&urb->use_count);
                if (urb->reject)
                        wake_up (&usb_kill_urb_queue);
@@ -1255,42 +1262,59 @@ rescan:
 
 #ifdef CONFIG_PM
 
-int hcd_bus_suspend (struct usb_bus *bus)
+int hcd_bus_suspend(struct usb_device *rhdev)
 {
-       struct usb_hcd          *hcd;
-       int                     status;
+       struct usb_hcd  *hcd = container_of(rhdev->bus, struct usb_hcd, self);
+       int             status;
+       int             old_state = hcd->state;
 
-       hcd = container_of (bus, struct usb_hcd, self);
-       if (!hcd->driver->bus_suspend)
-               return -ENOENT;
-       hcd->state = HC_STATE_QUIESCING;
-       status = hcd->driver->bus_suspend (hcd);
-       if (status == 0)
+       dev_dbg(&rhdev->dev, "bus %s%s\n",
+                       rhdev->auto_pm ? "auto-" : "", "suspend");
+       if (!hcd->driver->bus_suspend) {
+               status = -ENOENT;
+       } else {
+               hcd->state = HC_STATE_QUIESCING;
+               status = hcd->driver->bus_suspend(hcd);
+       }
+       if (status == 0) {
+               usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
                hcd->state = HC_STATE_SUSPENDED;
-       else
-               dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+       } else {
+               hcd->state = old_state;
+               dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
                                "suspend", status);
+       }
        return status;
 }
 
-int hcd_bus_resume (struct usb_bus *bus)
+int hcd_bus_resume(struct usb_device *rhdev)
 {
-       struct usb_hcd          *hcd;
-       int                     status;
+       struct usb_hcd  *hcd = container_of(rhdev->bus, struct usb_hcd, self);
+       int             status;
+       int             old_state = hcd->state;
 
-       hcd = container_of (bus, struct usb_hcd, self);
+       dev_dbg(&rhdev->dev, "usb %s%s\n",
+                       rhdev->auto_pm ? "auto-" : "", "resume");
        if (!hcd->driver->bus_resume)
                return -ENOENT;
        if (hcd->state == HC_STATE_RUNNING)
                return 0;
+
        hcd->state = HC_STATE_RESUMING;
-       status = hcd->driver->bus_resume (hcd);
-       if (status == 0)
+       status = hcd->driver->bus_resume(hcd);
+       if (status == 0) {
+               /* TRSMRCY = 10 msec */
+               msleep(10);
+               usb_set_device_state(rhdev, rhdev->actconfig
+                               ? USB_STATE_CONFIGURED
+                               : USB_STATE_ADDRESS);
                hcd->state = HC_STATE_RUNNING;
-       else {
-               dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+       } else {
+               hcd->state = old_state;
+               dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
                                "resume", status);
-               usb_hc_died(hcd);
+               if (status != -ESHUTDOWN)
+                       usb_hc_died(hcd);
        }
        return status;
 }
@@ -1384,30 +1408,10 @@ EXPORT_SYMBOL (usb_bus_start_enum);
  */
 void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
 {
-       int at_root_hub;
-
-       at_root_hub = (urb->dev == hcd->self.root_hub);
-       urb_unlink (urb);
-
-       /* lower level hcd code should use *_dma exclusively if the
-        * host controller does DMA */
-       if (hcd->self.uses_dma && !at_root_hub) {
-               if (usb_pipecontrol (urb->pipe)
-                       && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
-                       dma_unmap_single (hcd->self.controller, urb->setup_dma,
-                                       sizeof (struct usb_ctrlrequest),
-                                       DMA_TO_DEVICE);
-               if (urb->transfer_buffer_length != 0
-                       && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
-                       dma_unmap_single (hcd->self.controller, 
-                                       urb->transfer_dma,
-                                       urb->transfer_buffer_length,
-                                       usb_pipein (urb->pipe)
-                                           ? DMA_FROM_DEVICE
-                                           : DMA_TO_DEVICE);
-       }
-
+       urb_unlink(hcd, urb);
        usbmon_urb_complete (&hcd->self, urb);
+       usb_unanchor_urb(urb);
+
        /* pass ownership to the completion handler */
        urb->complete (urb);
        atomic_dec (&urb->use_count);
index ef50fa494e47838ec852e744bb689c9bb863065f..b5ebb73c23328cd5e65292f542d3d946e5ea9459 100644 (file)
@@ -364,23 +364,13 @@ extern int usb_find_interface_driver (struct usb_device *dev,
 #ifdef CONFIG_PM
 extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
 extern void usb_root_hub_lost_power (struct usb_device *rhdev);
-extern int hcd_bus_suspend (struct usb_bus *bus);
-extern int hcd_bus_resume (struct usb_bus *bus);
+extern int hcd_bus_suspend(struct usb_device *rhdev);
+extern int hcd_bus_resume(struct usb_device *rhdev);
 #else
 static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
 {
        return;
 }
-
-static inline int hcd_bus_suspend(struct usb_bus *bus)
-{
-       return 0;
-}
-
-static inline int hcd_bus_resume (struct usb_bus *bus)
-{
-       return 0;
-}
 #endif /* CONFIG_PM */
 
 /*
index 24f10a19dbdbc1bbbf6befd31da7018078cfa186..50e79010401cd42050062d52d1c1e9876cc0aa53 100644 (file)
 #include "hcd.h"
 #include "hub.h"
 
+#ifdef CONFIG_USB_PERSIST
+#define        USB_PERSIST     1
+#else
+#define        USB_PERSIST     0
+#endif
+
 struct usb_hub {
        struct device           *intfdev;       /* the "interface" device */
        struct usb_device       *hdev;
+       struct kref             kref;
        struct urb              *urb;           /* for interrupt polling pipe */
 
        /* buffer for urb ... with extra space in case of babble */
@@ -66,6 +73,7 @@ struct usb_hub {
        unsigned                limited_power:1;
        unsigned                quiescing:1;
        unsigned                activating:1;
+       unsigned                disconnected:1;
 
        unsigned                has_indicators:1;
        u8                      indicator[USB_MAXCHILDREN];
@@ -321,7 +329,7 @@ static void kick_khubd(struct usb_hub *hub)
        to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
 
        spin_lock_irqsave(&hub_event_lock, flags);
-       if (list_empty(&hub->event_list)) {
+       if (!hub->disconnected & list_empty(&hub->event_list)) {
                list_add_tail(&hub->event_list, &hub_event_list);
                wake_up(&khubd_wait);
        }
@@ -330,6 +338,7 @@ static void kick_khubd(struct usb_hub *hub)
 
 void usb_kick_khubd(struct usb_device *hdev)
 {
+       /* FIXME: What if hdev isn't bound to the hub driver? */
        kick_khubd(hdev_to_hub(hdev));
 }
 
@@ -400,9 +409,10 @@ static void hub_tt_kevent (struct work_struct *work)
        struct usb_hub          *hub =
                container_of(work, struct usb_hub, tt.kevent);
        unsigned long           flags;
+       int                     limit = 100;
 
        spin_lock_irqsave (&hub->tt.lock, flags);
-       while (!list_empty (&hub->tt.clear_list)) {
+       while (--limit && !list_empty (&hub->tt.clear_list)) {
                struct list_head        *temp;
                struct usb_tt_clear     *clear;
                struct usb_device       *hdev = hub->hdev;
@@ -550,48 +560,68 @@ static int hub_hub_status(struct usb_hub *hub,
 static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
 {
        struct usb_device *hdev = hub->hdev;
-       int ret;
+       int ret = 0;
 
-       if (hdev->children[port1-1] && set_state) {
+       if (hdev->children[port1-1] && set_state)
                usb_set_device_state(hdev->children[port1-1],
                                USB_STATE_NOTATTACHED);
-       }
-       ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
+       if (!hub->error)
+               ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
        if (ret)
                dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
-                       port1, ret);
-
+                               port1, ret);
        return ret;
 }
 
+/*
+ * Disable a port and mark a logical connnect-change event, so that some
+ * time later khubd will disconnect() any existing usb_device on the port
+ * and will re-enumerate if there actually is a device attached.
+ */
+static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+{
+       dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
+       hub_port_disable(hub, port1, 1);
+
+       /* FIXME let caller ask to power down the port:
+        *  - some devices won't enumerate without a VBUS power cycle
+        *  - SRP saves power that way
+        *  - ... new call, TBD ...
+        * That's easy if this hub can switch power per-port, and
+        * khubd reactivates the port later (timer, SRP, etc).
+        * Powerdown must be optional, because of reset/DFU.
+        */
+
+       set_bit(port1, hub->change_bits);
+       kick_khubd(hub);
+}
 
 /* caller has locked the hub device */
-static void hub_pre_reset(struct usb_interface *intf)
+static int hub_pre_reset(struct usb_interface *intf)
 {
        struct usb_hub *hub = usb_get_intfdata(intf);
        struct usb_device *hdev = hub->hdev;
-       int port1;
+       int i;
 
-       for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
-               if (hdev->children[port1 - 1]) {
-                       usb_disconnect(&hdev->children[port1 - 1]);
-                       if (hub->error == 0)
-                               hub_port_disable(hub, port1, 0);
-               }
+       /* Disconnect all the children */
+       for (i = 0; i < hdev->maxchild; ++i) {
+               if (hdev->children[i])
+                       usb_disconnect(&hdev->children[i]);
        }
        hub_quiesce(hub);
+       return 0;
 }
 
 /* caller has locked the hub device */
-static void hub_post_reset(struct usb_interface *intf)
+static int hub_post_reset(struct usb_interface *intf)
 {
        struct usb_hub *hub = usb_get_intfdata(intf);
 
-       hub_activate(hub);
        hub_power_on(hub);
+       hub_activate(hub);
+       return 0;
 }
 
-
 static int hub_configure(struct usb_hub *hub,
        struct usb_endpoint_descriptor *endpoint)
 {
@@ -845,43 +875,42 @@ fail:
        return ret;
 }
 
+static void hub_release(struct kref *kref)
+{
+       struct usb_hub *hub = container_of(kref, struct usb_hub, kref);
+
+       usb_put_intf(to_usb_interface(hub->intfdev));
+       kfree(hub);
+}
+
 static unsigned highspeed_hubs;
 
 static void hub_disconnect(struct usb_interface *intf)
 {
        struct usb_hub *hub = usb_get_intfdata (intf);
-       struct usb_device *hdev;
+
+       /* Take the hub off the event list and don't let it be added again */
+       spin_lock_irq(&hub_event_lock);
+       list_del_init(&hub->event_list);
+       hub->disconnected = 1;
+       spin_unlock_irq(&hub_event_lock);
 
        /* Disconnect all children and quiesce the hub */
        hub->error = 0;
        hub_pre_reset(intf);
 
        usb_set_intfdata (intf, NULL);
-       hdev = hub->hdev;
 
-       if (hdev->speed == USB_SPEED_HIGH)
+       if (hub->hdev->speed == USB_SPEED_HIGH)
                highspeed_hubs--;
 
        usb_free_urb(hub->urb);
-       hub->urb = NULL;
-
-       spin_lock_irq(&hub_event_lock);
-       list_del_init(&hub->event_list);
-       spin_unlock_irq(&hub_event_lock);
-
        kfree(hub->descriptor);
-       hub->descriptor = NULL;
-
        kfree(hub->status);
-       hub->status = NULL;
-
-       if (hub->buffer) {
-               usb_buffer_free(hdev, sizeof(*hub->buffer), hub->buffer,
-                               hub->buffer_dma);
-               hub->buffer = NULL;
-       }
+       usb_buffer_free(hub->hdev, sizeof(*hub->buffer), hub->buffer,
+                       hub->buffer_dma);
 
-       kfree(hub);
+       kref_put(&hub->kref, hub_release);
 }
 
 static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -929,10 +958,12 @@ descriptor_error:
                return -ENOMEM;
        }
 
+       kref_init(&hub->kref);
        INIT_LIST_HEAD(&hub->event_list);
        hub->intfdev = &intf->dev;
        hub->hdev = hdev;
        INIT_DELAYED_WORK(&hub->leds, led_work);
+       usb_get_intf(intf);
 
        usb_set_intfdata (intf, hub);
        intf->needs_remote_wakeup = 1;
@@ -982,49 +1013,6 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
 }
 
 
-/* grab device/port lock, returning index of that port (zero based).
- * protects the upstream link used by this device from concurrent
- * tree operations like suspend, resume, reset, and disconnect, which
- * apply to everything downstream of a given port.
- */
-static int locktree(struct usb_device *udev)
-{
-       int                     t;
-       struct usb_device       *hdev;
-
-       if (!udev)
-               return -ENODEV;
-
-       /* root hub is always the first lock in the series */
-       hdev = udev->parent;
-       if (!hdev) {
-               usb_lock_device(udev);
-               return 0;
-       }
-
-       /* on the path from root to us, lock everything from
-        * top down, dropping parent locks when not needed
-        */
-       t = locktree(hdev);
-       if (t < 0)
-               return t;
-
-       /* everything is fail-fast once disconnect
-        * processing starts
-        */
-       if (udev->state == USB_STATE_NOTATTACHED) {
-               usb_unlock_device(hdev);
-               return -ENODEV;
-       }
-
-       /* when everyone grabs locks top->bottom,
-        * non-overlapping work may be concurrent
-        */
-       usb_lock_device(udev);
-       usb_unlock_device(hdev);
-       return udev->portnum;
-}
-
 static void recursively_mark_NOTATTACHED(struct usb_device *udev)
 {
        int i;
@@ -1089,46 +1077,6 @@ void usb_set_device_state(struct usb_device *udev,
        spin_unlock_irqrestore(&device_state_lock, flags);
 }
 
-
-#ifdef CONFIG_PM
-
-/**
- * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
- * @rhdev: struct usb_device for the root hub
- *
- * The USB host controller driver calls this function when its root hub
- * is resumed and Vbus power has been interrupted or the controller
- * has been reset.  The routine marks all the children of the root hub
- * as NOTATTACHED and marks logical connect-change events on their ports.
- */
-void usb_root_hub_lost_power(struct usb_device *rhdev)
-{
-       struct usb_hub *hub;
-       int port1;
-       unsigned long flags;
-
-       dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
-
-       /* Make sure no potential wakeup events get lost,
-        * by forcing the root hub to be resumed.
-        */
-       rhdev->dev.power.prev_state.event = PM_EVENT_ON;
-
-       spin_lock_irqsave(&device_state_lock, flags);
-       hub = hdev_to_hub(rhdev);
-       for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
-               if (rhdev->children[port1 - 1]) {
-                       recursively_mark_NOTATTACHED(
-                                       rhdev->children[port1 - 1]);
-                       set_bit(port1, hub->change_bits);
-               }
-       }
-       spin_unlock_irqrestore(&device_state_lock, flags);
-}
-EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
-
-#endif /* CONFIG_PM */
-
 static void choose_address(struct usb_device *udev)
 {
        int             devnum;
@@ -1269,7 +1217,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
 
 #ifdef CONFIG_USB_OTG
 #include "otg_whitelist.h"
-static int __usb_port_suspend(struct usb_device *, int port1);
 #endif
 
 /**
@@ -1375,11 +1322,11 @@ int usb_new_device(struct usb_device *udev)
                 * (Includes HNP test device.)
                 */
                if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
-                       err = __usb_port_suspend(udev, udev->bus->otg_port);
+                       err = usb_port_suspend(udev);
                        if (err < 0)
                                dev_dbg(&udev->dev, "HNP fail, %d\n", err);
                }
-               err = -ENODEV;
+               err = -ENOTSUPP;
                goto fail;
        }
 #endif
@@ -1476,9 +1423,9 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
                if (!(portstatus & USB_PORT_STAT_CONNECTION))
                        return -ENOTCONN;
 
-               /* bomb out completely if something weird happened */
+               /* bomb out completely if the connection bounced */
                if ((portchange & USB_PORT_STAT_C_CONNECTION))
-                       return -EINVAL;
+                       return -ENOTCONN;
 
                /* if we`ve finished resetting, then break out of the loop */
                if (!(portstatus & USB_PORT_STAT_RESET) &&
@@ -1557,34 +1504,24 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
        return status;
 }
 
-/*
- * Disable a port and mark a logical connnect-change event, so that some
- * time later khubd will disconnect() any existing usb_device on the port
- * and will re-enumerate if there actually is a device attached.
- */
-static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
-{
-       dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
-       hub_port_disable(hub, port1, 1);
-
-       /* FIXME let caller ask to power down the port:
-        *  - some devices won't enumerate without a VBUS power cycle
-        *  - SRP saves power that way
-        *  - ... new call, TBD ...
-        * That's easy if this hub can switch power per-port, and
-        * khubd reactivates the port later (timer, SRP, etc).
-        * Powerdown must be optional, because of reset/DFU.
-        */
-
-       set_bit(port1, hub->change_bits);
-       kick_khubd(hub);
-}
-
 #ifdef CONFIG_PM
 
 #ifdef CONFIG_USB_SUSPEND
 
 /*
+ * usb_port_suspend - suspend a usb device's upstream port
+ * @udev: device that's no longer in active use, not a root hub
+ * Context: must be able to sleep; device not locked; pm locks held
+ *
+ * Suspends a USB device that isn't in active use, conserving power.
+ * Devices may wake out of a suspend, if anything important happens,
+ * using the remote wakeup mechanism.  They may also be taken out of
+ * suspend by the host, using usb_port_resume().  It's also routine
+ * to disconnect devices while they are suspended.
+ *
+ * This only affects the USB hardware for a device; its interfaces
+ * (and, for hubs, child devices) must already have been suspended.
+ *
  * Selective port suspend reduces power; most suspended devices draw
  * less than 500 uA.  It's also used in OTG, along with remote wakeup.
  * All devices below the suspended port are also suspended.
@@ -1593,11 +1530,35 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
  * also support "remote wakeup", where the device can activate the USB
  * tree above them to deliver data, such as a keypress or packet.  In
  * some cases, this wakes the USB host.
+ *
+ * Suspending OTG devices may trigger HNP, if that's been enabled
+ * between a pair of dual-role devices.  That will change roles, such
+ * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
+ *
+ * Devices on USB hub ports have only one "suspend" state, corresponding
+ * to ACPI D2, "may cause the device to lose some context".
+ * State transitions include:
+ *
+ *   - suspend, resume ... when the VBUS power link stays live
+ *   - suspend, disconnect ... VBUS lost
+ *
+ * Once VBUS drop breaks the circuit, the port it's using has to go through
+ * normal re-enumeration procedures, starting with enabling VBUS power.
+ * Other than re-initializing the hub (plug/unplug, except for root hubs),
+ * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
+ * timer, no SRP, no requests through sysfs.
+ *
+ * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
+ * the root hub for their bus goes into global suspend ... so we don't
+ * (falsely) update the device power state to say it suspended.
+ *
+ * Returns 0 on success, else negative errno.
  */
-static int hub_port_suspend(struct usb_hub *hub, int port1,
-               struct usb_device *udev)
+int usb_port_suspend(struct usb_device *udev)
 {
-       int     status;
+       struct usb_hub  *hub = hdev_to_hub(udev->parent);
+       int             port1 = udev->portnum;
+       int             status;
 
        // dev_dbg(hub->intfdev, "suspend port %d\n", port1);
 
@@ -1614,17 +1575,15 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
                                NULL, 0,
                                USB_CTRL_SET_TIMEOUT);
                if (status)
-                       dev_dbg(&udev->dev,
-                               "won't remote wakeup, status %d\n",
-                               status);
+                       dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
+                                       status);
        }
 
        /* see 7.1.7.6 */
        status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND);
        if (status) {
-               dev_dbg(hub->intfdev,
-                       "can't suspend port %d, status %d\n",
-                       port1, status);
+               dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
+                               port1, status);
                /* paranoia:  "should not happen" */
                (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
@@ -1641,86 +1600,25 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
        return status;
 }
 
-/*
- * Devices on USB hub ports have only one "suspend" state, corresponding
- * to ACPI D2, "may cause the device to lose some context".
- * State transitions include:
- *
- *   - suspend, resume ... when the VBUS power link stays live
- *   - suspend, disconnect ... VBUS lost
- *
- * Once VBUS drop breaks the circuit, the port it's using has to go through
- * normal re-enumeration procedures, starting with enabling VBUS power.
- * Other than re-initializing the hub (plug/unplug, except for root hubs),
- * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
- * timer, no SRP, no requests through sysfs.
- *
- * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
- * the root hub for their bus goes into global suspend ... so we don't
- * (falsely) update the device power state to say it suspended.
- */
-static int __usb_port_suspend (struct usb_device *udev, int port1)
-{
-       int     status = 0;
-
-       /* caller owns the udev device lock */
-       if (port1 < 0)
-               return port1;
-
-       /* we change the device's upstream USB link,
-        * but root hubs have no upstream USB link.
-        */
-       if (udev->parent)
-               status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
-                               udev);
-       else {
-               dev_dbg(&udev->dev, "usb %ssuspend\n",
-                               udev->auto_pm ? "auto-" : "");
-               usb_set_device_state(udev, USB_STATE_SUSPENDED);
-       }
-       return status;
-}
-
-/*
- * usb_port_suspend - suspend a usb device's upstream port
- * @udev: device that's no longer in active use
- * Context: must be able to sleep; device not locked; pm locks held
- *
- * Suspends a USB device that isn't in active use, conserving power.
- * Devices may wake out of a suspend, if anything important happens,
- * using the remote wakeup mechanism.  They may also be taken out of
- * suspend by the host, using usb_port_resume().  It's also routine
- * to disconnect devices while they are suspended.
- *
- * This only affects the USB hardware for a device; its interfaces
- * (and, for hubs, child devices) must already have been suspended.
- *
- * Suspending OTG devices may trigger HNP, if that's been enabled
- * between a pair of dual-role devices.  That will change roles, such
- * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
- *
- * Returns 0 on success, else negative errno.
- */
-int usb_port_suspend(struct usb_device *udev)
-{
-       return __usb_port_suspend(udev, udev->portnum);
-}
-
 /*
  * If the USB "suspend" state is in use (rather than "global suspend"),
  * many devices will be individually taken out of suspend state using
- * special" resume" signaling.  These routines kick in shortly after
+ * special "resume" signaling.  This routine kicks in shortly after
  * hardware resume signaling is finished, either because of selective
  * resume (by host) or remote wakeup (by device) ... now see what changed
  * in the tree that's rooted at this device.
+ *
+ * If @udev->reset_resume is set then the device is reset before the
+ * status check is done.
  */
 static int finish_port_resume(struct usb_device *udev)
 {
-       int     status;
+       int     status = 0;
        u16     devstatus;
 
        /* caller owns the udev device lock */
-       dev_dbg(&udev->dev, "finish resume\n");
+       dev_dbg(&udev->dev, "finish %sresume\n",
+                       udev->reset_resume ? "reset-" : "");
 
        /* usb ch9 identifies four variants of SUSPENDED, based on what
         * state the device resumes to.  Linux currently won't see the
@@ -1731,22 +1629,30 @@ static int finish_port_resume(struct usb_device *udev)
                        ? USB_STATE_CONFIGURED
                        : USB_STATE_ADDRESS);
 
+       /* 10.5.4.5 says not to reset a suspended port if the attached
+        * device is enabled for remote wakeup.  Hence the reset
+        * operation is carried out here, after the port has been
+        * resumed.
+        */
+       if (udev->reset_resume)
+               status = usb_reset_device(udev);
+
        /* 10.5.4.5 says be sure devices in the tree are still there.
         * For now let's assume the device didn't go crazy on resume,
         * and device drivers will know about any resume quirks.
         */
-       status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
-       if (status >= 0)
-               status = (status == 2 ? 0 : -ENODEV);
+       if (status == 0) {
+               status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+               if (status >= 0)
+                       status = (status == 2 ? 0 : -ENODEV);
+       }
 
-       if (status)
-               dev_dbg(&udev->dev,
-                       "gone after usb resume? status %d\n",
-                       status);
-       else if (udev->actconfig) {
+       if (status) {
+               dev_dbg(&udev->dev, "gone after usb resume? status %d\n",
+                               status);
+       } else if (udev->actconfig) {
                le16_to_cpus(&devstatus);
-               if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
-                               && udev->parent) {
+               if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
                        status = usb_control_msg(udev,
                                        usb_sndctrlpipe(udev, 0),
                                        USB_REQ_CLEAR_FEATURE,
@@ -1759,19 +1665,52 @@ static int finish_port_resume(struct usb_device *udev)
                                        "wakeup, status %d\n", status);
                }
                status = 0;
-
-       } else if (udev->devnum <= 0) {
-               dev_dbg(&udev->dev, "bogus resume!\n");
-               status = -EINVAL;
        }
        return status;
 }
 
-static int
-hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+/*
+ * usb_port_resume - re-activate a suspended usb device's upstream port
+ * @udev: device to re-activate, not a root hub
+ * Context: must be able to sleep; device not locked; pm locks held
+ *
+ * This will re-activate the suspended device, increasing power usage
+ * while letting drivers communicate again with its endpoints.
+ * USB resume explicitly guarantees that the power session between
+ * the host and the device is the same as it was when the device
+ * suspended.
+ *
+ * If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this
+ * routine won't check that the port is still enabled.  Furthermore,
+ * if @udev->reset_resume is set then finish_port_resume() above will
+ * reset @udev.  The end result is that a broken power session can be
+ * recovered and @udev will appear to persist across a loss of VBUS power.
+ *
+ * For example, if a host controller doesn't maintain VBUS suspend current
+ * during a system sleep or is reset when the system wakes up, all the USB
+ * power sessions below it will be broken.  This is especially troublesome
+ * for mass-storage devices containing mounted filesystems, since the
+ * device will appear to have disconnected and all the memory mappings
+ * to it will be lost.  Using the USB_PERSIST facility, the device can be
+ * made to appear as if it had not disconnected.
+ *
+ * This facility is inherently dangerous.  Although usb_reset_device()
+ * makes every effort to insure that the same device is present after the
+ * reset as before, it cannot provide a 100% guarantee.  Furthermore it's
+ * quite possible for a device to remain unaltered but its media to be
+ * changed.  If the user replaces a flash memory card while the system is
+ * asleep, he will have only himself to blame when the filesystem on the
+ * new card is corrupted and the system crashes.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int usb_port_resume(struct usb_device *udev)
 {
-       int     status;
-       u16     portchange, portstatus;
+       struct usb_hub  *hub = hdev_to_hub(udev->parent);
+       int             port1 = udev->portnum;
+       int             status;
+       u16             portchange, portstatus;
+       unsigned        mask_flags, want_flags;
 
        /* Skip the initial Clear-Suspend step for a remote wakeup */
        status = hub_port_status(hub, port1, &portstatus, &portchange);
@@ -1786,30 +1725,31 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
        status = clear_port_feature(hub->hdev,
                        port1, USB_PORT_FEAT_SUSPEND);
        if (status) {
-               dev_dbg(hub->intfdev,
-                       "can't resume port %d, status %d\n",
-                       port1, status);
+               dev_dbg(hub->intfdev, "can't resume port %d, status %d\n",
+                               port1, status);
        } else {
                /* drive resume for at least 20 msec */
-               if (udev)
-                       dev_dbg(&udev->dev, "usb %sresume\n",
-                                       udev->auto_pm ? "auto-" : "");
+               dev_dbg(&udev->dev, "usb %sresume\n",
+                               udev->auto_pm ? "auto-" : "");
                msleep(25);
 
-#define LIVE_FLAGS     ( USB_PORT_STAT_POWER \
-                       | USB_PORT_STAT_ENABLE \
-                       | USB_PORT_STAT_CONNECTION)
-
                /* Virtual root hubs can trigger on GET_PORT_STATUS to
                 * stop resume signaling.  Then finish the resume
                 * sequence.
                 */
                status = hub_port_status(hub, port1, &portstatus, &portchange);
-SuspendCleared:
-               if (status < 0
-                               || (portstatus & LIVE_FLAGS) != LIVE_FLAGS
-                               || (portstatus & USB_PORT_STAT_SUSPEND) != 0
-                               ) {
+
+ SuspendCleared:
+               if (USB_PERSIST && udev->reset_resume)
+                       want_flags = USB_PORT_STAT_POWER
+                                       | USB_PORT_STAT_CONNECTION;
+               else
+                       want_flags = USB_PORT_STAT_POWER
+                                       | USB_PORT_STAT_CONNECTION
+                                       | USB_PORT_STAT_ENABLE;
+               mask_flags = want_flags | USB_PORT_STAT_SUSPEND;
+
+               if (status < 0 || (portstatus & mask_flags) != want_flags) {
                        dev_dbg(hub->intfdev,
                                "port %d status %04x.%04x after resume, %d\n",
                                port1, portchange, portstatus, status);
@@ -1821,51 +1761,19 @@ SuspendCleared:
                                                USB_PORT_FEAT_C_SUSPEND);
                        /* TRSMRCY = 10 msec */
                        msleep(10);
-                       if (udev)
-                               status = finish_port_resume(udev);
                }
        }
-       if (status < 0)
-               hub_port_logical_disconnect(hub, port1);
 
        clear_bit(port1, hub->busy_bits);
        if (!hub->hdev->parent && !hub->busy_bits[0])
                usb_enable_root_hub_irq(hub->hdev->bus);
 
-       return status;
-}
-
-/*
- * usb_port_resume - re-activate a suspended usb device's upstream port
- * @udev: device to re-activate
- * Context: must be able to sleep; device not locked; pm locks held
- *
- * This will re-activate the suspended device, increasing power usage
- * while letting drivers communicate again with its endpoints.
- * USB resume explicitly guarantees that the power session between
- * the host and the device is the same as it was when the device
- * suspended.
- *
- * Returns 0 on success, else negative errno.
- */
-int usb_port_resume(struct usb_device *udev)
-{
-       int     status;
-
-       /* we change the device's upstream USB link,
-        * but root hubs have no upstream USB link.
-        */
-       if (udev->parent) {
-               // NOTE this fails if parent is also suspended...
-               status = hub_port_resume(hdev_to_hub(udev->parent),
-                               udev->portnum, udev);
-       } else {
-               dev_dbg(&udev->dev, "usb %sresume\n",
-                               udev->auto_pm ? "auto-" : "");
+       if (status == 0)
                status = finish_port_resume(udev);
-       }
-       if (status < 0)
+       if (status < 0) {
                dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+               hub_port_logical_disconnect(hub, port1);
+       }
        return status;
 }
 
@@ -1892,21 +1800,16 @@ int usb_port_suspend(struct usb_device *udev)
        return 0;
 }
 
-static inline int
-finish_port_resume(struct usb_device *udev)
-{
-       return 0;
-}
-
-static inline int
-hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
-{
-       return 0;
-}
-
 int usb_port_resume(struct usb_device *udev)
 {
-       return 0;
+       int status = 0;
+
+       /* However we may need to do a reset-resume */
+       if (udev->reset_resume) {
+               dev_dbg(&udev->dev, "reset-resume\n");
+               status = usb_reset_device(udev);
+       }
+       return status;
 }
 
 static inline int remote_wakeup(struct usb_device *udev)
@@ -1921,7 +1824,6 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
        struct usb_hub          *hub = usb_get_intfdata (intf);
        struct usb_device       *hdev = hub->hdev;
        unsigned                port1;
-       int                     status = 0;
 
        /* fail if children aren't already suspended */
        for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -1947,49 +1849,75 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 
        /* stop khubd and related activity */
        hub_quiesce(hub);
-
-       /* "global suspend" of the downstream HC-to-USB interface */
-       if (!hdev->parent) {
-               status = hcd_bus_suspend(hdev->bus);
-               if (status != 0) {
-                       dev_dbg(&hdev->dev, "'global' suspend %d\n", status);
-                       hub_activate(hub);
-               }
-       }
-       return status;
+       return 0;
 }
 
 static int hub_resume(struct usb_interface *intf)
 {
        struct usb_hub          *hub = usb_get_intfdata (intf);
-       struct usb_device       *hdev = hub->hdev;
-       int                     status;
 
        dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
 
-       /* "global resume" of the downstream HC-to-USB interface */
-       if (!hdev->parent) {
-               struct usb_bus  *bus = hdev->bus;
-               if (bus) {
-                       status = hcd_bus_resume (bus);
-                       if (status) {
-                               dev_dbg(&intf->dev, "'global' resume %d\n",
-                                       status);
-                               return status;
+       /* tell khubd to look for changes on this hub */
+       hub_activate(hub);
+       return 0;
+}
+
+static int hub_reset_resume(struct usb_interface *intf)
+{
+       struct usb_hub *hub = usb_get_intfdata(intf);
+       struct usb_device *hdev = hub->hdev;
+       int port1;
+
+       hub_power_on(hub);
+
+       for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+               struct usb_device *child = hdev->children[port1-1];
+
+               if (child) {
+
+                       /* For "USB_PERSIST"-enabled children we must
+                        * mark the child device for reset-resume and
+                        * turn off the connect-change status to prevent
+                        * khubd from disconnecting it later.
+                        */
+                       if (USB_PERSIST && child->persist_enabled) {
+                               child->reset_resume = 1;
+                               clear_port_feature(hdev, port1,
+                                               USB_PORT_FEAT_C_CONNECTION);
+
+                       /* Otherwise we must disconnect the child,
+                        * but as we may not lock the child device here
+                        * we have to do a "logical" disconnect.
+                        */
+                       } else {
+                               hub_port_logical_disconnect(hub, port1);
                        }
-               } else
-                       return -EOPNOTSUPP;
-               if (status == 0) {
-                       /* TRSMRCY = 10 msec */
-                       msleep(10);
                }
        }
 
-       /* tell khubd to look for changes on this hub */
        hub_activate(hub);
        return 0;
 }
 
+/**
+ * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
+ * @rhdev: struct usb_device for the root hub
+ *
+ * The USB host controller driver calls this function when its root hub
+ * is resumed and Vbus power has been interrupted or the controller
+ * has been reset.  The routine marks @rhdev as having lost power.  When
+ * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST
+ * is enabled then it will carry out power-session recovery, otherwise
+ * it will disconnect all the child devices.
+ */
+void usb_root_hub_lost_power(struct usb_device *rhdev)
+{
+       dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
+       rhdev->reset_resume = 1;
+}
+EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
+
 #else  /* CONFIG_PM */
 
 static inline int remote_wakeup(struct usb_device *udev)
@@ -1997,8 +1925,9 @@ static inline int remote_wakeup(struct usb_device *udev)
        return 0;
 }
 
-#define hub_suspend NULL
-#define hub_resume NULL
+#define hub_suspend            NULL
+#define hub_resume             NULL
+#define hub_reset_resume       NULL
 #endif
 
 
@@ -2461,19 +2390,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
                return;
        }
 
-#ifdef  CONFIG_USB_SUSPEND
-       /* If something is connected, but the port is suspended, wake it up. */
-       if (portstatus & USB_PORT_STAT_SUSPEND) {
-               status = hub_port_resume(hub, port1, NULL);
-               if (status < 0) {
-                       dev_dbg(hub_dev,
-                               "can't clear suspend on port %d; %d\n",
-                               port1, status);
-                       goto done;
-               }
-       }
-#endif
-
        for (i = 0; i < SET_CONFIG_TRIES; i++) {
                struct usb_device *udev;
 
@@ -2584,7 +2500,7 @@ loop:
                ep0_reinit(udev);
                release_address(udev);
                usb_put_dev(udev);
-               if (status == -ENOTCONN)
+               if ((status == -ENOTCONN) || (status == -ENOTSUPP))
                        break;
        }
  
@@ -2625,10 +2541,12 @@ static void hub_events(void)
                list_del_init(tmp);
 
                hub = list_entry(tmp, struct usb_hub, event_list);
-               hdev = hub->hdev;
-               intf = to_usb_interface(hub->intfdev);
-               hub_dev = &intf->dev;
+               kref_get(&hub->kref);
+               spin_unlock_irq(&hub_event_lock);
 
+               hdev = hub->hdev;
+               hub_dev = hub->intfdev;
+               intf = to_usb_interface(hub_dev);
                dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
                                hdev->state, hub->descriptor
                                        ? hub->descriptor->bNbrPorts
@@ -2637,16 +2555,10 @@ static void hub_events(void)
                                (u16) hub->change_bits[0],
                                (u16) hub->event_bits[0]);
 
-               usb_get_intf(intf);
-               spin_unlock_irq(&hub_event_lock);
-
                /* Lock the device, then check to see if we were
                 * disconnected while waiting for the lock to succeed. */
-               if (locktree(hdev) < 0) {
-                       usb_put_intf(intf);
-                       continue;
-               }
-               if (hub != usb_get_intfdata(intf))
+               usb_lock_device(hdev);
+               if (unlikely(hub->disconnected))
                        goto loop;
 
                /* If the hub has died, clean up after it */
@@ -2809,7 +2721,7 @@ loop_autopm:
                        usb_autopm_enable(intf);
 loop:
                usb_unlock_device(hdev);
-               usb_put_intf(intf);
+               kref_put(&hub->kref, hub_release);
 
         } /* end while (1) */
 }
@@ -2844,6 +2756,7 @@ static struct usb_driver hub_driver = {
        .disconnect =   hub_disconnect,
        .suspend =      hub_suspend,
        .resume =       hub_resume,
+       .reset_resume = hub_reset_resume,
        .pre_reset =    hub_pre_reset,
        .post_reset =   hub_post_reset,
        .ioctl =        hub_ioctl,
@@ -2946,6 +2859,11 @@ static int config_descriptors_changed(struct usb_device *udev)
  * this from a driver probe() routine after downloading new firmware.
  * For calls that might not occur during probe(), drivers should lock
  * the device using usb_lock_device_for_reset().
+ *
+ * Locking exception: This routine may also be called from within an
+ * autoresume handler.  Such usage won't conflict with other tasks
+ * holding the device lock because these tasks should always call
+ * usb_autopm_resume_device(), thereby preventing any unwanted autoresume.
  */
 int usb_reset_device(struct usb_device *udev)
 {
@@ -2976,7 +2894,7 @@ int usb_reset_device(struct usb_device *udev)
                 * Other endpoints will be handled by re-enumeration. */
                ep0_reinit(udev);
                ret = hub_port_init(parent_hub, udev, port1, i);
-               if (ret >= 0)
+               if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
                        break;
        }
        clear_bit(port1, parent_hub->busy_bits);
@@ -3092,6 +3010,7 @@ int usb_reset_composite_device(struct usb_device *udev,
                                drv = to_usb_driver(cintf->dev.driver);
                                if (drv->pre_reset)
                                        (drv->pre_reset)(cintf);
+       /* FIXME: Unbind if pre_reset returns an error or isn't defined */
                        }
                }
        }
@@ -3110,6 +3029,7 @@ int usb_reset_composite_device(struct usb_device *udev,
                                drv = to_usb_driver(cintf->dev.driver);
                                if (drv->post_reset)
                                        (drv->post_reset)(cintf);
+       /* FIXME: Unbind if post_reset returns an error or isn't defined */
                        }
                        if (cintf != iface)
                                up(&cintf->dev.sem);
index f9fed34bf7d8b307491aee6d91c84edd686f28ed..530e854961ce99785291b399d92253151c626d9e 100644 (file)
@@ -404,8 +404,6 @@ int usb_sg_init (
 
                io->urbs [i]->complete = sg_complete;
                io->urbs [i]->context = io;
-               io->urbs [i]->status = -EINPROGRESS;
-               io->urbs [i]->actual_length = 0;
 
                /*
                 * Some systems need to revert to PIO when DMA is temporarily
@@ -499,7 +497,8 @@ void usb_sg_wait (struct usb_sg_request *io)
 
        /* queue the urbs.  */
        spin_lock_irq (&io->lock);
-       for (i = 0; i < entries && !io->status; i++) {
+       i = 0;
+       while (i < entries && !io->status) {
                int     retval;
 
                io->urbs [i]->dev = io->dev;
@@ -516,7 +515,6 @@ void usb_sg_wait (struct usb_sg_request *io)
                case -ENOMEM:
                        io->urbs[i]->dev = NULL;
                        retval = 0;
-                       i--;
                        yield ();
                        break;
 
@@ -527,6 +525,7 @@ void usb_sg_wait (struct usb_sg_request *io)
                         * URBs are queued at once; N milliseconds?
                         */
                case 0:
+                       ++i;
                        cpu_relax ();
                        break;
 
@@ -1385,6 +1384,36 @@ struct device_type usb_if_device_type = {
        .uevent =       usb_if_uevent,
 };
 
+static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
+                                                      struct usb_host_config *config,
+                                                      u8 inum)
+{
+       struct usb_interface_assoc_descriptor *retval = NULL;
+       struct usb_interface_assoc_descriptor *intf_assoc;
+       int first_intf;
+       int last_intf;
+       int i;
+
+       for (i = 0; (i < USB_MAXIADS && config->intf_assoc[i]); i++) {
+               intf_assoc = config->intf_assoc[i];
+               if (intf_assoc->bInterfaceCount == 0)
+                       continue;
+
+               first_intf = intf_assoc->bFirstInterface;
+               last_intf = first_intf + (intf_assoc->bInterfaceCount - 1);
+               if (inum >= first_intf && inum <= last_intf) {
+                       if (!retval)
+                               retval = intf_assoc;
+                       else
+                               dev_err(&dev->dev, "Interface #%d referenced"
+                                       " by multiple IADs\n", inum);
+               }
+       }
+
+       return retval;
+}
+
+
 /*
  * usb_set_configuration - Makes a particular device setting be current
  * @dev: the device whose configuration is being updated
@@ -1531,6 +1560,7 @@ free_interfaces:
                intfc = cp->intf_cache[i];
                intf->altsetting = intfc->altsetting;
                intf->num_altsetting = intfc->num_altsetting;
+               intf->intf_assoc = find_iad(dev, cp, i);
                kref_get(&intfc->ref);
 
                alt = usb_altnum_to_altsetting(intf, 0);
index 739f520908aa939b30a09e54bd3a9627b6ceb0a5..aa21b38a31cee53bca3af2cb0ca9ea8fd89ac64c 100644 (file)
 static const struct usb_device_id usb_quirk_list[] = {
        /* HP 5300/5370C scanner */
        { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
+       /* Benq S2W 3300U */
+       { USB_DEVICE(0x04a5, 0x20b0), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+       /* Seiko Epson Corp. Perfection 1200 */
+       { USB_DEVICE(0x04b8, 0x0104), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
        /* Seiko Epson Corp - Perfection 1670 */
        { USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+       /* Samsung ML-2510 Series printer */
+       { USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
        /* Elsa MicroLink 56k (V.250) */
        { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+       /* Ultima Electronics Corp.*/
+       { USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+       /* Umax [hex] Astra 3400U */
+       { USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+
+       /* Philips PSC805 audio device */
+       { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* RIM Blackberry */
+       { USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+       { USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+       { USB_DEVICE(0x0fca, 0x0006), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 
        { }  /* terminating entry must be last */
 };
index be37c863fdfb18e872e553af1b8c5778a67e67a6..d47ae89154a7e7b4a2d9ab40e4e733eaebe124be 100644 (file)
@@ -169,6 +169,73 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
 }
 static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
 
+
+#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND)
+static const char power_group[] = "power";
+#endif
+
+#ifdef CONFIG_USB_PERSIST
+
+static ssize_t
+show_persist(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct usb_device *udev = to_usb_device(dev);
+
+       return sprintf(buf, "%d\n", udev->persist_enabled);
+}
+
+static ssize_t
+set_persist(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct usb_device *udev = to_usb_device(dev);
+       int value;
+
+       /* Hubs are always enabled for USB_PERSIST */
+       if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+               return -EPERM;
+
+       if (sscanf(buf, "%d", &value) != 1)
+               return -EINVAL;
+       usb_pm_lock(udev);
+       udev->persist_enabled = !!value;
+       usb_pm_unlock(udev);
+       return count;
+}
+
+static DEVICE_ATTR(persist, S_IRUGO | S_IWUSR, show_persist, set_persist);
+
+static int add_persist_attributes(struct device *dev)
+{
+       int rc = 0;
+
+       if (is_usb_device(dev)) {
+               struct usb_device *udev = to_usb_device(dev);
+
+               /* Hubs are automatically enabled for USB_PERSIST */
+               if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+                       udev->persist_enabled = 1;
+               rc = sysfs_add_file_to_group(&dev->kobj,
+                               &dev_attr_persist.attr,
+                               power_group);
+       }
+       return rc;
+}
+
+static void remove_persist_attributes(struct device *dev)
+{
+       sysfs_remove_file_from_group(&dev->kobj,
+                       &dev_attr_persist.attr,
+                       power_group);
+}
+
+#else
+
+#define add_persist_attributes(dev)    0
+#define remove_persist_attributes(dev) do {} while (0)
+
+#endif /* CONFIG_USB_PERSIST */
+
 #ifdef CONFIG_USB_SUSPEND
 
 static ssize_t
@@ -276,8 +343,6 @@ set_level(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
 
-static char power_group[] = "power";
-
 static int add_power_attributes(struct device *dev)
 {
        int rc = 0;
@@ -311,6 +376,7 @@ static void remove_power_attributes(struct device *dev)
 
 #endif /* CONFIG_USB_SUSPEND */
 
+
 /* Descriptor fields */
 #define usb_descriptor_attr_le16(field, format_string)                 \
 static ssize_t                                                         \
@@ -384,6 +450,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
        if (retval)
                return retval;
 
+       retval = add_persist_attributes(dev);
+       if (retval)
+               goto error;
+
        retval = add_power_attributes(dev);
        if (retval)
                goto error;
@@ -421,9 +491,29 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
        device_remove_file(dev, &dev_attr_product);
        device_remove_file(dev, &dev_attr_serial);
        remove_power_attributes(dev);
+       remove_persist_attributes(dev);
        sysfs_remove_group(&dev->kobj, &dev_attr_grp);
 }
 
+/* Interface Accociation Descriptor fields */
+#define usb_intf_assoc_attr(field, format_string)                      \
+static ssize_t                                                         \
+show_iad_##field (struct device *dev, struct device_attribute *attr,   \
+               char *buf)                                              \
+{                                                                      \
+       struct usb_interface *intf = to_usb_interface (dev);            \
+                                                                       \
+       return sprintf (buf, format_string,                             \
+                       intf->intf_assoc->field);               \
+}                                                                      \
+static DEVICE_ATTR(iad_##field, S_IRUGO, show_iad_##field, NULL);
+
+usb_intf_assoc_attr (bFirstInterface, "%02x\n")
+usb_intf_assoc_attr (bInterfaceCount, "%02d\n")
+usb_intf_assoc_attr (bFunctionClass, "%02x\n")
+usb_intf_assoc_attr (bFunctionSubClass, "%02x\n")
+usb_intf_assoc_attr (bFunctionProtocol, "%02x\n")
+
 /* Interface fields */
 #define usb_intf_attr(field, format_string)                            \
 static ssize_t                                                         \
@@ -487,6 +577,18 @@ static ssize_t show_modalias(struct device *dev,
 }
 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
 
+static struct attribute *intf_assoc_attrs[] = {
+       &dev_attr_iad_bFirstInterface.attr,
+       &dev_attr_iad_bInterfaceCount.attr,
+       &dev_attr_iad_bFunctionClass.attr,
+       &dev_attr_iad_bFunctionSubClass.attr,
+       &dev_attr_iad_bFunctionProtocol.attr,
+       NULL,
+};
+static struct attribute_group intf_assoc_attr_grp = {
+       .attrs = intf_assoc_attrs,
+};
+
 static struct attribute *intf_attrs[] = {
        &dev_attr_bInterfaceNumber.attr,
        &dev_attr_bAlternateSetting.attr,
@@ -538,6 +640,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
                alt->string = usb_cache_string(udev, alt->desc.iInterface);
        if (alt->string)
                retval = device_create_file(dev, &dev_attr_interface);
+       if (intf->intf_assoc)
+               retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp);
        usb_create_intf_ep_files(intf, udev);
        return 0;
 }
@@ -549,4 +653,5 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf)
        usb_remove_intf_ep_files(intf);
        device_remove_file(dev, &dev_attr_interface);
        sysfs_remove_group(&dev->kobj, &intf_attr_grp);
+       sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp);
 }
index 94ea9727ff55d4c4018acdc18f4eb7f8bca775a6..52ec44b828f3530dd8dfdb33e8452be6aa2a819f 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/usb.h>
+#include <linux/wait.h>
 #include "hcd.h"
 
 #define to_urb(d) container_of(d, struct urb, kref)
 static void urb_destroy(struct kref *kref)
 {
        struct urb *urb = to_urb(kref);
+
+       if (urb->transfer_flags & URB_FREE_BUFFER)
+               kfree(urb->transfer_buffer);
+
        kfree(urb);
 }
 
@@ -34,6 +39,7 @@ void usb_init_urb(struct urb *urb)
                memset(urb, 0, sizeof(*urb));
                kref_init(&urb->kref);
                spin_lock_init(&urb->lock);
+               INIT_LIST_HEAD(&urb->anchor_list);
        }
 }
 
@@ -100,8 +106,60 @@ struct urb * usb_get_urb(struct urb *urb)
                kref_get(&urb->kref);
        return urb;
 }
-               
-               
+
+/**
+ * usb_anchor_urb - anchors an URB while it is processed
+ * @urb: pointer to the urb to anchor
+ * @anchor: pointer to the anchor
+ *
+ * This can be called to have access to URBs which are to be executed
+ * without bothering to track them
+ */
+void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&anchor->lock, flags);
+       usb_get_urb(urb);
+       list_add_tail(&urb->anchor_list, &anchor->urb_list);
+       urb->anchor = anchor;
+       spin_unlock_irqrestore(&anchor->lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_anchor_urb);
+
+/**
+ * usb_unanchor_urb - unanchors an URB
+ * @urb: pointer to the urb to anchor
+ *
+ * Call this to stop the system keeping track of this URB
+ */
+void usb_unanchor_urb(struct urb *urb)
+{
+       unsigned long flags;
+       struct usb_anchor *anchor;
+
+       if (!urb)
+               return;
+
+       anchor = urb->anchor;
+       if (!anchor)
+               return;
+
+       spin_lock_irqsave(&anchor->lock, flags);
+       if (unlikely(anchor != urb->anchor)) {
+               /* we've lost the race to another thread */
+               spin_unlock_irqrestore(&anchor->lock, flags);
+               return;
+       }
+       urb->anchor = NULL;
+       list_del(&urb->anchor_list);
+       spin_unlock_irqrestore(&anchor->lock, flags);
+       usb_put_urb(urb);
+       if (list_empty(&anchor->urb_list))
+               wake_up(&anchor->wait);
+}
+EXPORT_SYMBOL_GPL(usb_unanchor_urb);
+
 /*-------------------------------------------------------------------*/
 
 /**
@@ -478,6 +536,48 @@ void usb_kill_urb(struct urb *urb)
        spin_unlock_irq(&urb->lock);
 }
 
+/**
+ * usb_kill_anchored_urbs - cancel transfer requests en masse
+ * @anchor: anchor the requests are bound to
+ *
+ * this allows all outstanding URBs to be killed starting
+ * from the back of the queue
+ */
+void usb_kill_anchored_urbs(struct usb_anchor *anchor)
+{
+       struct urb *victim;
+
+       spin_lock_irq(&anchor->lock);
+       while (!list_empty(&anchor->urb_list)) {
+               victim = list_entry(anchor->urb_list.prev, struct urb, anchor_list);
+               /* we must make sure the URB isn't freed before we kill it*/
+               usb_get_urb(victim);
+               spin_unlock_irq(&anchor->lock);
+               /* this will unanchor the URB */
+               usb_kill_urb(victim);
+               usb_put_urb(victim);
+               spin_lock_irq(&anchor->lock);
+       }
+       spin_unlock_irq(&anchor->lock);
+}
+EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
+
+/**
+ * usb_wait_anchor_empty_timeout - wait for an anchor to be unused
+ * @anchor: the anchor you want to become unused
+ * @timeout: how long you are willing to wait in milliseconds
+ *
+ * Call this is you want to be sure all an anchor's
+ * URBs have finished
+ */
+int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
+                                 unsigned int timeout)
+{
+       return wait_event_timeout(anchor->wait, list_empty(&anchor->urb_list),
+                                 msecs_to_jiffies(timeout));
+}
+EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout);
+
 EXPORT_SYMBOL(usb_init_urb);
 EXPORT_SYMBOL(usb_alloc_urb);
 EXPORT_SYMBOL(usb_free_urb);
@@ -485,4 +585,3 @@ EXPORT_SYMBOL(usb_get_urb);
 EXPORT_SYMBOL(usb_submit_urb);
 EXPORT_SYMBOL(usb_unlink_urb);
 EXPORT_SYMBOL(usb_kill_urb);
-
index 4a6299bd00478156417a7ed757ffc0d261bdc736..0fee5c66fd64ea44ef0531453b1b0bfb60cc7614 100644 (file)
@@ -253,6 +253,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
        dev->dev.bus = &usb_bus_type;
        dev->dev.type = &usb_device_type;
        dev->dev.dma_mask = bus->controller->dma_mask;
+       set_dev_node(&dev->dev, dev_to_node(bus->controller));
        dev->state = USB_STATE_ATTACHED;
 
        INIT_LIST_HEAD(&dev->ep0.urb_list);
@@ -578,11 +579,12 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
  * address (through the pointer provided).
  *
  * These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags
- * to avoid behaviors like using "DMA bounce buffers", or tying down I/O
- * mapping hardware for long idle periods.  The implementation varies between
+ * to avoid behaviors like using "DMA bounce buffers", or thrashing IOMMU
+ * hardware during URB completion/resubmit.  The implementation varies between
  * platforms, depending on details of how DMA will work to this device.
- * Using these buffers also helps prevent cacheline sharing problems on
- * architectures where CPU caches are not DMA-coherent.
+ * Using these buffers also eliminates cacheline sharing problems on
+ * architectures where CPU caches are not DMA-coherent.  On systems without
+ * bus-snooping caches, these buffers are uncached.
  *
  * When the buffer is no longer used, free it with usb_buffer_free().
  */
@@ -607,7 +609,7 @@ void *usb_buffer_alloc(
  *
  * This reclaims an I/O buffer, letting it be reused.  The memory must have
  * been allocated using usb_buffer_alloc(), and the parameters must match
- * those provided in that allocation request. 
+ * those provided in that allocation request.
  */
 void usb_buffer_free(
        struct usb_device *dev,
index bf2eb0dae2ecc3aeee8e08f2c941d59513c733fe..ad5fa0338f498631ca71350b198830b3f80ac3fb 100644 (file)
@@ -52,8 +52,16 @@ static inline void usb_pm_unlock(struct usb_device *udev)
 
 #else
 
-#define usb_port_suspend(dev)          0
-#define usb_port_resume(dev)           0
+static inline int usb_port_suspend(struct usb_device *udev)
+{
+       return 0;
+}
+
+static inline int usb_port_resume(struct usb_device *udev)
+{
+       return 0;
+}
+
 static inline void usb_pm_lock(struct usb_device *udev) {}
 static inline void usb_pm_unlock(struct usb_device *udev) {}
 
@@ -100,11 +108,13 @@ static inline int is_usb_device_driver(struct device_driver *drv)
 static inline void mark_active(struct usb_interface *f)
 {
        f->is_active = 1;
+       f->dev.power.power_state.event = PM_EVENT_ON;
 }
 
 static inline void mark_quiesced(struct usb_interface *f)
 {
        f->is_active = 0;
+       f->dev.power.power_state.event = PM_EVENT_SUSPEND;
 }
 
 static inline int is_active(const struct usb_interface *f)
index f771a7cae9ece36ce0085f871beac7c38199ce13..45e01e289455376b68e5f5ceca8ca3a3a2937ec3 100644 (file)
@@ -42,6 +42,20 @@ config USB_GADGET
           For more information, see <http://www.linux-usb.org/gadget> and
           the kernel DocBook documentation for this API.
 
+config USB_GADGET_DEBUG
+       boolean "Debugging messages"
+       depends on USB_GADGET && DEBUG_KERNEL && EXPERIMENTAL
+       help
+          Many controller and gadget drivers will print some debugging
+          messages if you use this option to ask for those messages.
+
+          Avoid enabling these messages, even if you're actively
+          debugging such a driver.  Many drivers will emit so many
+          messages that the driver timings are affected, which will
+          either create new failure modes or remove the one you're
+          trying to track down.  Never enable these messages for a
+          production build.
+
 config USB_GADGET_DEBUG_FILES
        boolean "Debugging information files"
        depends on USB_GADGET && PROC_FS
@@ -208,6 +222,27 @@ config USB_OTG
 
           Select this only if your OMAP board has a Mini-AB connector.
 
+config USB_GADGET_S3C2410
+       boolean "S3C2410 USB Device Controller"
+       depends on ARCH_S3C2410
+       help
+         Samsung's S3C2410 is an ARM-4 processor with an integrated
+         full speed USB 1.1 device controller.  It has 4 configurable
+         endpoints, as well as endpoint zero (for control transfers).
+
+         This driver has been tested on the S3C2410, S3C2412, and
+         S3C2440 processors.
+
+config USB_S3C2410
+       tristate
+       depends on USB_GADGET_S3C2410
+       default USB_GADGET
+       select USB_GADGET_SELECTED
+
+config USB_S3C2410_DEBUG
+       boolean "S3C2410 udc debug messages"
+       depends on USB_GADGET_S3C2410
+
 config USB_GADGET_AT91
        boolean "AT91 USB Device Port"
        depends on ARCH_AT91 && !ARCH_AT91SAM9RL
@@ -226,6 +261,24 @@ config USB_AT91
        depends on USB_GADGET_AT91
        default USB_GADGET
 
+config USB_GADGET_M66592
+       boolean "M66592 driver"
+       select USB_GADGET_DUALSPEED
+       help
+          M66592 is a USB 2.0 peripheral controller.
+
+          It has seven configurable endpoints, and endpoint zero.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "m66592_udc" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_M66592
+       tristate
+       depends on USB_GADGET_M66592
+       default USB_GADGET
+       select USB_GADGET_SELECTED
+
 config USB_GADGET_DUMMY_HCD
        boolean "Dummy HCD (DEVELOPMENT)"
        depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL
index 5db19396631c49732ea4c0f0de94683020d78bdc..8ae76f7386355074ffba6b3d1fb1a326e323becd 100644 (file)
@@ -1,14 +1,20 @@
 #
 # USB peripheral controller drivers
 #
+ifeq ($(CONFIG_USB_GADGET_DEBUG),y)
+       EXTRA_CFLAGS            += -DDEBUG
+endif
+
 obj-$(CONFIG_USB_DUMMY_HCD)    += dummy_hcd.o
 obj-$(CONFIG_USB_NET2280)      += net2280.o
 obj-$(CONFIG_USB_PXA2XX)       += pxa2xx_udc.o
 obj-$(CONFIG_USB_GOKU)         += goku_udc.o
 obj-$(CONFIG_USB_OMAP)         += omap_udc.o
 obj-$(CONFIG_USB_LH7A40X)      += lh7a40x_udc.o
+obj-$(CONFIG_USB_S3C2410)      += s3c2410_udc.o
 obj-$(CONFIG_USB_AT91)         += at91_udc.o
 obj-$(CONFIG_USB_FSL_USB2)     += fsl_usb2_udc.o
+obj-$(CONFIG_USB_M66592)       += m66592-udc.o
 
 #
 # USB gadget drivers
index ba163f35bf21efd984431d3c3626ed85bab61989..63d7d6568699e28fad912c05c3fc4f7c601bf39d 100644 (file)
@@ -601,25 +601,6 @@ static void at91_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
        kfree(req);
 }
 
-static void *at91_ep_alloc_buffer(
-       struct usb_ep *_ep,
-       unsigned bytes,
-       dma_addr_t *dma,
-       gfp_t gfp_flags)
-{
-       *dma = ~0;
-       return kmalloc(bytes, gfp_flags);
-}
-
-static void at91_ep_free_buffer(
-       struct usb_ep *ep,
-       void *buf,
-       dma_addr_t dma,
-       unsigned bytes)
-{
-       kfree(buf);
-}
-
 static int at91_ep_queue(struct usb_ep *_ep,
                        struct usb_request *_req, gfp_t gfp_flags)
 {
@@ -788,8 +769,6 @@ static const struct usb_ep_ops at91_ep_ops = {
        .disable        = at91_ep_disable,
        .alloc_request  = at91_ep_alloc_request,
        .free_request   = at91_ep_free_request,
-       .alloc_buffer   = at91_ep_alloc_buffer,
-       .free_buffer    = at91_ep_free_buffer,
        .queue          = at91_ep_queue,
        .dequeue        = at91_ep_dequeue,
        .set_halt       = at91_ep_set_halt,
index fcb5526cb085d68658bc936fd93650af9a3e33c4..f2fbdc7fe376ddf7397f056ab78eee74bc19f427 100644 (file)
@@ -497,38 +497,6 @@ dummy_free_request (struct usb_ep *_ep, struct usb_request *_req)
        kfree (req);
 }
 
-static void *
-dummy_alloc_buffer (
-       struct usb_ep *_ep,
-       unsigned bytes,
-       dma_addr_t *dma,
-       gfp_t mem_flags
-) {
-       char                    *retval;
-       struct dummy_ep         *ep;
-       struct dummy            *dum;
-
-       ep = usb_ep_to_dummy_ep (_ep);
-       dum = ep_to_dummy (ep);
-
-       if (!dum->driver)
-               return NULL;
-       retval = kmalloc (bytes, mem_flags);
-       *dma = (dma_addr_t) retval;
-       return retval;
-}
-
-static void
-dummy_free_buffer (
-       struct usb_ep *_ep,
-       void *buf,
-       dma_addr_t dma,
-       unsigned bytes
-) {
-       if (bytes)
-               kfree (buf);
-}
-
 static void
 fifo_complete (struct usb_ep *ep, struct usb_request *req)
 {
@@ -659,10 +627,6 @@ static const struct usb_ep_ops dummy_ep_ops = {
        .alloc_request  = dummy_alloc_request,
        .free_request   = dummy_free_request,
 
-       .alloc_buffer   = dummy_alloc_buffer,
-       .free_buffer    = dummy_free_buffer,
-       /* map, unmap, ... eventually hook the "generic" dma calls */
-
        .queue          = dummy_queue,
        .dequeue        = dummy_dequeue,
 
@@ -1784,8 +1748,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd)
 
        spin_lock_irq (&dum->lock);
        if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
-               dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
-               rc = -ENODEV;
+               rc = -ESHUTDOWN;
        } else {
                dum->rh_state = DUMMY_RH_RUNNING;
                set_link_state (dum);
index 325bf7cfb83ffd04d76ab3cccf2d984f2618db8c..dbaf867436dffbc69e3172810fd4b24a89d7c10f 100644 (file)
@@ -277,7 +277,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
 #define DEV_CONFIG_CDC
 #endif
 
-#ifdef CONFIG_USB_GADGET_HUSB2DEV
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
 #define DEV_CONFIG_CDC
 #endif
 
@@ -292,7 +292,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
 #define        DEV_CONFIG_SUBSET
 #endif
 
-#ifdef CONFIG_USB_GADGET_SH
+#ifdef CONFIG_USB_GADGET_SUPERH
 #define        DEV_CONFIG_SUBSET
 #endif
 
@@ -301,6 +301,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
 #define        DEV_CONFIG_SUBSET
 #endif
 
+#ifdef CONFIG_USB_GADGET_M66592
+#define DEV_CONFIG_CDC
+#endif
+
 
 /*-------------------------------------------------------------------------*/
 
index 4639b629e60ca02af90a05756a8359342c86bda9..8712ef987179b2ca2ba4ed3c6d26df9823395ed9 100644 (file)
@@ -3733,19 +3733,12 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
        }
 
        /* Free the data buffers */
-       for (i = 0; i < NUM_BUFFERS; ++i) {
-               struct fsg_buffhd       *bh = &fsg->buffhds[i];
-
-               if (bh->buf)
-                       usb_ep_free_buffer(fsg->bulk_in, bh->buf, bh->dma,
-                                       mod_data.buflen);
-       }
+       for (i = 0; i < NUM_BUFFERS; ++i)
+               kfree(fsg->buffhds[i].buf);
 
        /* Free the request and buffer for endpoint 0 */
        if (req) {
-               if (req->buf)
-                       usb_ep_free_buffer(fsg->ep0, req->buf,
-                                       req->dma, EP0_BUFSIZE);
+               kfree(req->buf);
                usb_ep_free_request(fsg->ep0, req);
        }
 
@@ -3963,8 +3956,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
 #endif
 
        if (gadget->is_otg) {
-               otg_desc.bmAttributes |= USB_OTG_HNP,
-               config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+               otg_desc.bmAttributes |= USB_OTG_HNP;
        }
 
        rc = -ENOMEM;
@@ -3973,8 +3965,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
        fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
        if (!req)
                goto out;
-       req->buf = usb_ep_alloc_buffer(fsg->ep0, EP0_BUFSIZE,
-                       &req->dma, GFP_KERNEL);
+       req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
        if (!req->buf)
                goto out;
        req->complete = ep0_complete;
@@ -3986,8 +3977,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
                /* Allocate for the bulk-in endpoint.  We assume that
                 * the buffer will also work with the bulk-out (and
                 * interrupt-in) endpoint. */
-               bh->buf = usb_ep_alloc_buffer(fsg->bulk_in, mod_data.buflen,
-                               &bh->dma, GFP_KERNEL);
+               bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
                if (!bh->buf)
                        goto out;
                bh->next = bh + 1;
index 3ca2b3159f00d8947a712ea45d96c09a6c72f72c..10b2b33b8698e54c48b3f2ce701cfa3c09c0406a 100644 (file)
@@ -228,7 +228,7 @@ static int dr_controller_setup(struct fsl_udc *udc)
 
        /* Config PHY interface */
        portctrl = fsl_readl(&dr_regs->portsc1);
-       portctrl &= ~(PORTSCX_PHY_TYPE_SEL & PORTSCX_PORT_WIDTH);
+       portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH);
        switch (udc->phy_mode) {
        case FSL_USB2_PHY_ULPI:
                portctrl |= PORTSCX_PTS_ULPI;
@@ -601,39 +601,6 @@ static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req)
                kfree(req);
 }
 
-/*------------------------------------------------------------------
- * Allocate an I/O buffer
-*---------------------------------------------------------------------*/
-static void *fsl_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-               dma_addr_t *dma, gfp_t gfp_flags)
-{
-       struct fsl_ep *ep;
-
-       if (!_ep)
-               return NULL;
-
-       ep = container_of(_ep, struct fsl_ep, ep);
-
-       return dma_alloc_coherent(ep->udc->gadget.dev.parent,
-                       bytes, dma, gfp_flags);
-}
-
-/*------------------------------------------------------------------
- * frees an i/o buffer
-*---------------------------------------------------------------------*/
-static void fsl_free_buffer(struct usb_ep *_ep, void *buf,
-               dma_addr_t dma, unsigned bytes)
-{
-       struct fsl_ep *ep;
-
-       if (!_ep)
-               return;
-
-       ep = container_of(_ep, struct fsl_ep, ep);
-
-       dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma);
-}
-
 /*-------------------------------------------------------------------------*/
 static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
 {
@@ -1047,9 +1014,6 @@ static struct usb_ep_ops fsl_ep_ops = {
        .alloc_request = fsl_alloc_request,
        .free_request = fsl_free_request,
 
-       .alloc_buffer = fsl_alloc_buffer,
-       .free_buffer = fsl_free_buffer,
-
        .queue = fsl_ep_queue,
        .dequeue = fsl_ep_dequeue,
 
@@ -2189,27 +2153,19 @@ static void fsl_udc_release(struct device *dev)
  * init resource for globle controller
  * Return the udc handle on success or NULL on failure
  ------------------------------------------------------------------*/
-static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev)
+static int __init struct_udc_setup(struct fsl_udc *udc,
+               struct platform_device *pdev)
 {
-       struct fsl_udc *udc;
        struct fsl_usb2_platform_data *pdata;
        size_t size;
 
-       udc = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
-       if (udc == NULL) {
-               ERR("malloc udc failed\n");
-               return NULL;
-       }
-
        pdata = pdev->dev.platform_data;
        udc->phy_mode = pdata->phy_mode;
-       /* max_ep_nr is bidirectional ep number, max_ep doubles the number */
-       udc->max_ep = pdata->max_ep_nr * 2;
 
        udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
        if (!udc->eps) {
                ERR("malloc fsl_ep failed\n");
-               goto cleanup;
+               return -1;
        }
 
        /* initialized QHs, take care of alignment */
@@ -2225,7 +2181,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev)
        if (!udc->ep_qh) {
                ERR("malloc QHs for udc failed\n");
                kfree(udc->eps);
-               goto cleanup;
+               return -1;
        }
 
        udc->ep_qh_size = size;
@@ -2244,11 +2200,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev)
        udc->remote_wakeup = 0; /* default to 0 on reset */
        spin_lock_init(&udc->lock);
 
-       return udc;
-
-cleanup:
-       kfree(udc);
-       return NULL;
+       return 0;
 }
 
 /*----------------------------------------------------------------
@@ -2287,35 +2239,37 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
 }
 
 /* Driver probe function
- * all intialize operations implemented here except enabling usb_intr reg
+ * all intialization operations implemented here except enabling usb_intr reg
+ * board setup should have been done in the platform code
  */
 static int __init fsl_udc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        int ret = -ENODEV;
        unsigned int i;
+       u32 dccparams;
 
        if (strcmp(pdev->name, driver_name)) {
                VDBG("Wrong device\n");
                return -ENODEV;
        }
 
-       /* board setup should have been done in the platform code */
-
-       /* Initialize the udc structure including QH member and other member */
-       udc_controller = struct_udc_setup(pdev);
-       if (!udc_controller) {
-               VDBG("udc_controller is NULL \n");
+       udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
+       if (udc_controller == NULL) {
+               ERR("malloc udc failed\n");
                return -ENOMEM;
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
+       if (!res) {
+               kfree(udc_controller);
                return -ENXIO;
+       }
 
        if (!request_mem_region(res->start, res->end - res->start + 1,
                                driver_name)) {
                ERR("request mem region for %s failed \n", pdev->name);
+               kfree(udc_controller);
                return -EBUSY;
        }
 
@@ -2328,13 +2282,24 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
        usb_sys_regs = (struct usb_sys_interface *)
                        ((u32)dr_regs + USB_DR_SYS_OFFSET);
 
+       /* Read Device Controller Capability Parameters register */
+       dccparams = fsl_readl(&dr_regs->dccparams);
+       if (!(dccparams & DCCPARAMS_DC)) {
+               ERR("This SOC doesn't support device role\n");
+               ret = -ENODEV;
+               goto err2;
+       }
+       /* Get max device endpoints */
+       /* DEN is bidirectional ep number, max_ep doubles the number */
+       udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2;
+
        udc_controller->irq = platform_get_irq(pdev, 0);
        if (!udc_controller->irq) {
                ret = -ENODEV;
                goto err2;
        }
 
-       ret = request_irq(udc_controller->irq, fsl_udc_irq, SA_SHIRQ,
+       ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED,
                        driver_name, udc_controller);
        if (ret != 0) {
                ERR("cannot request irq %d err %d \n",
@@ -2342,6 +2307,13 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
                goto err2;
        }
 
+       /* Initialize the udc structure including QH member and other member */
+       if (struct_udc_setup(udc_controller, pdev)) {
+               ERR("Can't initialize udc data structure\n");
+               ret = -ENOMEM;
+               goto err3;
+       }
+
        /* initialize usb hw reg except for regs for EP,
         * leave usbintr reg untouched */
        dr_controller_setup(udc_controller);
@@ -2403,6 +2375,7 @@ err2:
        iounmap(dr_regs);
 err1:
        release_mem_region(res->start, res->end - res->start + 1);
+       kfree(udc_controller);
        return ret;
 }
 
index c6291e046507776594fc4beecfa88b2acfdcfa23..832ab82b4882c9ad1d4ae7b5eb0e2aaff921c233 100644 (file)
@@ -101,6 +101,10 @@ struct usb_sys_interface {
 #define WAIT_FOR_OUT_STATUS     3
 #define DATA_STATE_RECV         4
 
+/* Device Controller Capability Parameter register */
+#define DCCPARAMS_DC                           0x00000080
+#define DCCPARAMS_DEN_MASK                     0x0000001f
+
 /* Frame Index Register Bit Masks */
 #define        USB_FRINDEX_MASKS                       0x3fff
 /* USB CMD  Register Bit Masks */
index d041b919e7b88ffd7f75f58e8ce7ee6040e2dd5f..53e9139ba3886137ac2f642eb72587183251a777 100644 (file)
@@ -8,6 +8,8 @@
  * (And avoiding all runtime comparisons in typical one-choice configs!)
  *
  * NOTE:  some of these controller drivers may not be available yet.
+ * Some are available on 2.4 kernels; several are available, but not
+ * yet pushed in the 2.6 mainline tree.
  */
 #ifdef CONFIG_USB_GADGET_NET2280
 #define        gadget_is_net2280(g)    !strcmp("net2280", (g)->name)
 #define        gadget_is_goku(g)       0
 #endif
 
+/* SH3 UDC -- not yet ported 2.4 --> 2.6 */
 #ifdef CONFIG_USB_GADGET_SUPERH
 #define        gadget_is_sh(g)         !strcmp("sh_udc", (g)->name)
 #else
 #define        gadget_is_sh(g)         0
 #endif
 
+/* not yet stable on 2.6 (would help "original Zaurus") */
 #ifdef CONFIG_USB_GADGET_SA1100
 #define        gadget_is_sa1100(g)     !strcmp("sa1100_udc", (g)->name)
 #else
@@ -51,6 +55,7 @@
 #define        gadget_is_lh7a40x(g)    0
 #endif
 
+/* handhelds.org tree (?) */
 #ifdef CONFIG_USB_GADGET_MQ11XX
 #define        gadget_is_mq11xx(g)     !strcmp("mq11xx_udc", (g)->name)
 #else
 #define        gadget_is_omap(g)       0
 #endif
 
+/* not yet ported 2.4 --> 2.6 */
 #ifdef CONFIG_USB_GADGET_N9604
 #define        gadget_is_n9604(g)      !strcmp("n9604_udc", (g)->name)
 #else
 #define        gadget_is_n9604(g)      0
 #endif
 
+/* various unstable versions available */
 #ifdef CONFIG_USB_GADGET_PXA27X
 #define        gadget_is_pxa27x(g)     !strcmp("pxa27x_udc", (g)->name)
 #else
 #define        gadget_is_pxa27x(g)     0
 #endif
 
-#ifdef CONFIG_USB_GADGET_HUSB2DEV
-#define gadget_is_husb2dev(g)  !strcmp("husb2_udc", (g)->name)
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+#define gadget_is_atmel_usba(g)        !strcmp("atmel_usba_udc", (g)->name)
 #else
-#define gadget_is_husb2dev(g)  0
+#define gadget_is_atmel_usba(g)        0
 #endif
 
 #ifdef CONFIG_USB_GADGET_S3C2410
 #define gadget_is_at91(g)      0
 #endif
 
+/* status unclear */
 #ifdef CONFIG_USB_GADGET_IMX
 #define gadget_is_imx(g)       !strcmp("imx_udc", (g)->name)
 #else
 #endif
 
 /* Mentor high speed function controller */
+/* from Montavista kernel (?) */
 #ifdef CONFIG_USB_GADGET_MUSBHSFC
 #define gadget_is_musbhsfc(g)  !strcmp("musbhsfc_udc", (g)->name)
 #else
 #define gadget_is_musbhdrc(g)  0
 #endif
 
+/* from Montavista kernel (?) */
 #ifdef CONFIG_USB_GADGET_MPC8272
 #define gadget_is_mpc8272(g)   !strcmp("mpc8272_udc", (g)->name)
 #else
 #define gadget_is_mpc8272(g)   0
 #endif
 
+#ifdef CONFIG_USB_GADGET_M66592
+#define        gadget_is_m66592(g)     !strcmp("m66592_udc", (g)->name)
+#else
+#define        gadget_is_m66592(g)     0
+#endif
+
+
 // CONFIG_USB_GADGET_SX2
 // CONFIG_USB_GADGET_AU1X00
 // ...
@@ -181,9 +198,11 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
                return 0x16;
        else if (gadget_is_mpc8272(gadget))
                return 0x17;
-       else if (gadget_is_husb2dev(gadget))
+       else if (gadget_is_atmel_usba(gadget))
                return 0x18;
        else if (gadget_is_fsl_usb2(gadget))
                return 0x19;
+       else if (gadget_is_m66592(gadget))
+               return 0x20;
        return -ENOENT;
 }
index d08a8d0e6427dc2d3276f622a037977b590957db..1c5aa49d74327ddff868671d50466d7931c83b30 100644 (file)
@@ -1248,17 +1248,11 @@ autoconf_fail:
        tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev);
 
        /* preallocate control response and buffer */
-       dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
+       dev->req = alloc_ep_req(gadget->ep0, USB_BUFSIZ);
        if (!dev->req) {
                err = -ENOMEM;
                goto fail;
        }
-       dev->req->buf = usb_ep_alloc_buffer(gadget->ep0, USB_BUFSIZ,
-                               &dev->req->dma, GFP_KERNEL);
-       if (!dev->req->buf) {
-               err = -ENOMEM;
-               goto fail;
-       }
 
        dev->req->complete = gmidi_setup_complete;
 
index ae931af05cef303521fbad67bfa858829c1fc359..d6c5f1150ae795c91cf9f7f928e81c4f8fed5040 100644 (file)
@@ -20,7 +20,6 @@
  *  - DMA works with ep1 (OUT transfers) and ep2 (IN transfers).
  */
 
-#undef DEBUG
 // #define     VERBOSE         /* extra debug messages (success too) */
 // #define     USB_TRACE       /* packet-level success messages */
 
@@ -296,51 +295,6 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req)
 
 /*-------------------------------------------------------------------------*/
 
-/* allocating buffers this way eliminates dma mapping overhead, which
- * on some platforms will mean eliminating a per-io buffer copy.  with
- * some kinds of system caches, further tweaks may still be needed.
- */
-static void *
-goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-                       dma_addr_t *dma, gfp_t gfp_flags)
-{
-       void            *retval;
-       struct goku_ep  *ep;
-
-       ep = container_of(_ep, struct goku_ep, ep);
-       if (!_ep)
-               return NULL;
-       *dma = DMA_ADDR_INVALID;
-
-       if (ep->dma) {
-               /* the main problem with this call is that it wastes memory
-                * on typical 1/N page allocations: it allocates 1-N pages.
-                */
-#warning Using dma_alloc_coherent even with buffers smaller than a page.
-               retval = dma_alloc_coherent(&ep->dev->pdev->dev,
-                               bytes, dma, gfp_flags);
-       } else
-               retval = kmalloc(bytes, gfp_flags);
-       return retval;
-}
-
-static void
-goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
-{
-       /* free memory into the right allocator */
-       if (dma != DMA_ADDR_INVALID) {
-               struct goku_ep  *ep;
-
-               ep = container_of(_ep, struct goku_ep, ep);
-               if (!_ep)
-                       return;
-               dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma);
-       } else
-               kfree (buf);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static void
 done(struct goku_ep *ep, struct goku_request *req, int status)
 {
@@ -485,7 +439,7 @@ top:
                        /* use ep1/ep2 double-buffering for OUT */
                        if (!(size & PACKET_ACTIVE))
                                size = readl(&regs->EPxSizeLB[ep->num]);
-                       if (!(size & PACKET_ACTIVE))    // "can't happen"
+                       if (!(size & PACKET_ACTIVE))    /* "can't happen" */
                                break;
                        size &= DATASIZE;       /* EPxSizeH == 0 */
 
@@ -1026,9 +980,6 @@ static struct usb_ep_ops goku_ep_ops = {
        .alloc_request  = goku_alloc_request,
        .free_request   = goku_free_request,
 
-       .alloc_buffer   = goku_alloc_buffer,
-       .free_buffer    = goku_free_buffer,
-
        .queue          = goku_queue,
        .dequeue        = goku_dequeue,
 
@@ -1140,17 +1091,17 @@ udc_proc_read(char *buffer, char **start, off_t off, int count,
                is_usb_connected
                        ? ((tmp & PW_PULLUP) ? "full speed" : "powered")
                        : "disconnected",
-               ({char *tmp;
+               ({char *state;
                switch(dev->ep0state){
-               case EP0_DISCONNECT:    tmp = "ep0_disconnect"; break;
-               case EP0_IDLE:          tmp = "ep0_idle"; break;
-               case EP0_IN:            tmp = "ep0_in"; break;
-               case EP0_OUT:           tmp = "ep0_out"; break;
-               case EP0_STATUS:        tmp = "ep0_status"; break;
-               case EP0_STALL:         tmp = "ep0_stall"; break;
-               case EP0_SUSPEND:       tmp = "ep0_suspend"; break;
-               default:                tmp = "ep0_?"; break;
-               } tmp; })
+               case EP0_DISCONNECT:    state = "ep0_disconnect"; break;
+               case EP0_IDLE:          state = "ep0_idle"; break;
+               case EP0_IN:            state = "ep0_in"; break;
+               case EP0_OUT:           state = "ep0_out"; break;
+               case EP0_STATUS:        state = "ep0_status"; break;
+               case EP0_STALL:         state = "ep0_stall"; break;
+               case EP0_SUSPEND:       state = "ep0_suspend"; break;
+               default:                state = "ep0_?"; break;
+               } state; })
                );
        size -= t;
        next += t;
@@ -1195,7 +1146,6 @@ udc_proc_read(char *buffer, char **start, off_t off, int count,
        for (i = 0; i < 4; i++) {
                struct goku_ep          *ep = &dev->ep [i];
                struct goku_request     *req;
-               int                     t;
 
                if (i && !ep->desc)
                        continue;
@@ -1283,7 +1233,7 @@ done:
 static void udc_reinit (struct goku_udc *dev)
 {
        static char *names [] = { "ep0", "ep1-bulk", "ep2-bulk", "ep3-bulk" };
-       
+
        unsigned i;
 
        INIT_LIST_HEAD (&dev->gadget.ep_list);
@@ -1896,9 +1846,9 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* done */
        the_controller = dev;
-       device_register(&dev->gadget.dev);
-
-       return 0;
+       retval = device_register(&dev->gadget.dev);
+       if (retval == 0)
+               return 0;
 
 done:
        if (dev)
@@ -1910,8 +1860,8 @@ done:
 /*-------------------------------------------------------------------------*/
 
 static struct pci_device_id pci_ids [] = { {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
+       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class_mask =   ~0,
        .vendor =       0x102f,         /* Toshiba */
        .device =       0x0107,         /* this UDC */
        .subvendor =    PCI_ANY_ID,
index ea8c8e58cabf1411382894853d2e507d2c3931d3..bc4eb1e0b507213c4da4ae1abbefdc7701340863 100644 (file)
@@ -41,8 +41,10 @@ struct goku_udc_regs {
 #define INT_SYSERROR           0x40000
 #define INT_PWRDETECT          0x80000
 
-#define        INT_DEVWIDE             (INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND)
-#define        INT_EP0                 (INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK)
+#define        INT_DEVWIDE \
+       (INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND)
+#define        INT_EP0 \
+       (INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK)
 
        u32     dma_master;
 #define MST_EOPB_DIS           0x0800
@@ -231,7 +233,7 @@ struct goku_request {
 enum ep0state {
        EP0_DISCONNECT,         /* no host */
        EP0_IDLE,               /* between STATUS ack and SETUP report */
-       EP0_IN, EP0_OUT,        /* data stage */
+       EP0_IN, EP0_OUT,        /* data stage */
        EP0_STATUS,             /* status stage */
        EP0_STALL,              /* data or status stages */
        EP0_SUSPEND,            /* usb suspend */
@@ -242,7 +244,7 @@ struct goku_udc {
        struct usb_gadget               gadget;
        spinlock_t                      lock;
        struct goku_ep                  ep[4];
-       struct usb_gadget_driver        *driver;
+       struct usb_gadget_driver        *driver;
 
        enum ep0state                   ep0state;
        unsigned                        got_irq:1,
index 46d0e52527447aea5d9f63073d964317dd0bd0a9..e60745ffaf8e382b71cab4203db168025475077b 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/device.h>
 #include <linux/moduleparam.h>
 
-#include <linux/usb_gadgetfs.h>
+#include <linux/usb/gadgetfs.h>
 #include <linux/usb_gadget.h>
 
 
@@ -923,7 +923,7 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req)
        struct dev_data         *dev = ep->driver_data;
 
        if (req->buf != dev->rbuf) {
-               usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
+               kfree(req->buf);
                req->buf = dev->rbuf;
                req->dma = DMA_ADDR_INVALID;
        }
@@ -963,7 +963,7 @@ static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len)
                return -EBUSY;
        }
        if (len > sizeof (dev->rbuf))
-               req->buf = usb_ep_alloc_buffer (ep, len, &req->dma, GFP_ATOMIC);
+               req->buf = kmalloc(len, GFP_ATOMIC);
        if (req->buf == 0) {
                req->buf = dev->rbuf;
                return -ENOMEM;
@@ -1505,7 +1505,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                }
                break;
 
-#ifndef        CONFIG_USB_GADGETFS_PXA2XX
+#ifndef        CONFIG_USB_GADGET_PXA2XX
        /* PXA automagically handles this request too */
        case USB_REQ_GET_CONFIGURATION:
                if (ctrl->bRequestType != 0x80)
index a0a73c08a34467730f007ed6bcf27bf4d8e7ae78..e78c2ddc1f88a47e6cbd52007d088f43269e8fee 100644 (file)
@@ -75,10 +75,6 @@ static int lh7a40x_ep_enable(struct usb_ep *ep,
 static int lh7a40x_ep_disable(struct usb_ep *ep);
 static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t);
 static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *);
-static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned, dma_addr_t *,
-                                 gfp_t);
-static void lh7a40x_free_buffer(struct usb_ep *ep, void *, dma_addr_t,
-                               unsigned);
 static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
 static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
 static int lh7a40x_set_halt(struct usb_ep *ep, int);
@@ -104,9 +100,6 @@ static struct usb_ep_ops lh7a40x_ep_ops = {
        .alloc_request = lh7a40x_alloc_request,
        .free_request = lh7a40x_free_request,
 
-       .alloc_buffer = lh7a40x_alloc_buffer,
-       .free_buffer = lh7a40x_free_buffer,
-
        .queue = lh7a40x_queue,
        .dequeue = lh7a40x_dequeue,
 
@@ -1134,26 +1127,6 @@ static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req)
        kfree(req);
 }
 
-static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes,
-                                 dma_addr_t * dma, gfp_t gfp_flags)
-{
-       char *retval;
-
-       DEBUG("%s (%p, %d, %d)\n", __FUNCTION__, ep, bytes, gfp_flags);
-
-       retval = kmalloc(bytes, gfp_flags & ~(__GFP_DMA | __GFP_HIGHMEM));
-       if (retval)
-               *dma = virt_to_bus(retval);
-       return retval;
-}
-
-static void lh7a40x_free_buffer(struct usb_ep *ep, void *buf, dma_addr_t dma,
-                               unsigned bytes)
-{
-       DEBUG("%s, %p\n", __FUNCTION__, ep);
-       kfree(buf);
-}
-
 /** Queue one request
  *  Kickstart transfer if needed
  *  NOTE: Sets INDEX register
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
new file mode 100644 (file)
index 0000000..c0a962b
--- /dev/null
@@ -0,0 +1,1653 @@
+/*
+ * M66592 UDC (USB gadget)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb_gadget.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "m66592-udc.h"
+
+MODULE_DESCRIPTION("M66592 USB gadget driiver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+
+#define DRIVER_VERSION "29 May 2007"
+
+/* module parameters */
+static unsigned short clock = M66592_XTAL24;
+module_param(clock, ushort, 0644);
+MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=16384)");
+static unsigned short vif = M66592_LDRV;
+module_param(vif, ushort, 0644);
+MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)");
+static unsigned short endian = 0;
+module_param(endian, ushort, 0644);
+MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)");
+static unsigned short irq_sense = M66592_INTL;
+module_param(irq_sense, ushort, 0644);
+MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0(default=2)");
+
+static const char udc_name[] = "m66592_udc";
+static const char *m66592_ep_name[] = {
+       "ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7"
+};
+
+static void disable_controller(struct m66592 *m66592);
+static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req);
+static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req);
+static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags);
+
+static void transfer_complete(struct m66592_ep *ep,
+                             struct m66592_request *req,
+                             int status);
+/*-------------------------------------------------------------------------*/
+static inline u16 get_usb_speed(struct m66592 *m66592)
+{
+       return (m66592_read(m66592, M66592_DVSTCTR) & M66592_RHST);
+}
+
+static void enable_pipe_irq(struct m66592 *m66592, u16 pipenum,
+                           unsigned long reg)
+{
+       u16 tmp;
+
+       tmp = m66592_read(m66592, M66592_INTENB0);
+       m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
+                   M66592_INTENB0);
+       m66592_bset(m66592, (1 << pipenum), reg);
+       m66592_write(m66592, tmp, M66592_INTENB0);
+}
+
+static void disable_pipe_irq(struct m66592 *m66592, u16 pipenum,
+                            unsigned long reg)
+{
+       u16 tmp;
+
+       tmp = m66592_read(m66592, M66592_INTENB0);
+       m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
+                   M66592_INTENB0);
+       m66592_bclr(m66592, (1 << pipenum), reg);
+       m66592_write(m66592, tmp, M66592_INTENB0);
+}
+
+static void m66592_usb_connect(struct m66592 *m66592)
+{
+       m66592_bset(m66592, M66592_CTRE, M66592_INTENB0);
+       m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
+                   M66592_INTENB0);
+       m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
+
+       m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
+}
+
+static void m66592_usb_disconnect(struct m66592 *m66592)
+{
+       m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0);
+       m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
+                   M66592_INTENB0);
+       m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
+       m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+
+       m66592->gadget.speed = USB_SPEED_UNKNOWN;
+       spin_unlock(&m66592->lock);
+       m66592->driver->disconnect(&m66592->gadget);
+       spin_lock(&m66592->lock);
+
+       disable_controller(m66592);
+       INIT_LIST_HEAD(&m66592->ep[0].queue);
+}
+
+static inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
+{
+       u16 pid = 0;
+       unsigned long offset;
+
+       if (pipenum == 0)
+               pid = m66592_read(m66592, M66592_DCPCTR) & M66592_PID;
+       else if (pipenum < M66592_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               pid = m66592_read(m66592, offset) & M66592_PID;
+       } else
+               printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+
+       return pid;
+}
+
+static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
+                                      u16 pid)
+{
+       unsigned long offset;
+
+       if (pipenum == 0)
+               m66592_mdfy(m66592, pid, M66592_PID, M66592_DCPCTR);
+       else if (pipenum < M66592_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               m66592_mdfy(m66592, pid, M66592_PID, offset);
+       } else
+               printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+}
+
+static inline void pipe_start(struct m66592 *m66592, u16 pipenum)
+{
+       control_reg_set_pid(m66592, pipenum, M66592_PID_BUF);
+}
+
+static inline void pipe_stop(struct m66592 *m66592, u16 pipenum)
+{
+       control_reg_set_pid(m66592, pipenum, M66592_PID_NAK);
+}
+
+static inline void pipe_stall(struct m66592 *m66592, u16 pipenum)
+{
+       control_reg_set_pid(m66592, pipenum, M66592_PID_STALL);
+}
+
+static inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
+{
+       u16 ret = 0;
+       unsigned long offset;
+
+       if (pipenum == 0)
+               ret = m66592_read(m66592, M66592_DCPCTR);
+       else if (pipenum < M66592_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               ret = m66592_read(m66592, offset);
+       } else
+               printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+
+       return ret;
+}
+
+static inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
+{
+       unsigned long offset;
+
+       pipe_stop(m66592, pipenum);
+
+       if (pipenum == 0)
+               m66592_bset(m66592, M66592_SQCLR, M66592_DCPCTR);
+       else if (pipenum < M66592_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               m66592_bset(m66592, M66592_SQCLR, offset);
+       } else
+               printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum);
+}
+
+static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
+{
+       u16 tmp;
+       int size;
+
+       if (pipenum == 0) {
+               tmp = m66592_read(m66592, M66592_DCPCFG);
+               if ((tmp & M66592_CNTMD) != 0)
+                       size = 256;
+               else {
+                       tmp = m66592_read(m66592, M66592_DCPMAXP);
+                       size = tmp & M66592_MAXP;
+               }
+       } else {
+               m66592_write(m66592, pipenum, M66592_PIPESEL);
+               tmp = m66592_read(m66592, M66592_PIPECFG);
+               if ((tmp & M66592_CNTMD) != 0) {
+                       tmp = m66592_read(m66592, M66592_PIPEBUF);
+                       size = ((tmp >> 10) + 1) * 64;
+               } else {
+                       tmp = m66592_read(m66592, M66592_PIPEMAXP);
+                       size = tmp & M66592_MXPS;
+               }
+       }
+
+       return size;
+}
+
+static inline void pipe_change(struct m66592 *m66592, u16 pipenum)
+{
+       struct m66592_ep *ep = m66592->pipenum2ep[pipenum];
+
+       if (ep->use_dma)
+               return;
+
+       m66592_mdfy(m66592, pipenum, M66592_CURPIPE, ep->fifosel);
+
+       ndelay(450);
+
+       m66592_bset(m66592, M66592_MBW, ep->fifosel);
+}
+
+static int pipe_buffer_setting(struct m66592 *m66592,
+                              struct m66592_pipe_info *info)
+{
+       u16 bufnum = 0, buf_bsize = 0;
+       u16 pipecfg = 0;
+
+       if (info->pipe == 0)
+               return -EINVAL;
+
+       m66592_write(m66592, info->pipe, M66592_PIPESEL);
+
+       if (info->dir_in)
+               pipecfg |= M66592_DIR;
+       pipecfg |= info->type;
+       pipecfg |= info->epnum;
+       switch (info->type) {
+       case M66592_INT:
+               bufnum = 4 + (info->pipe - M66592_BASE_PIPENUM_INT);
+               buf_bsize = 0;
+               break;
+       case M66592_BULK:
+               bufnum = m66592->bi_bufnum +
+                        (info->pipe - M66592_BASE_PIPENUM_BULK) * 16;
+               m66592->bi_bufnum += 16;
+               buf_bsize = 7;
+               pipecfg |= M66592_DBLB;
+               if (!info->dir_in)
+                       pipecfg |= M66592_SHTNAK;
+               break;
+       case M66592_ISO:
+               bufnum = m66592->bi_bufnum +
+                        (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
+               m66592->bi_bufnum += 16;
+               buf_bsize = 7;
+               break;
+       }
+       if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
+               printk(KERN_ERR "m66592 pipe memory is insufficient(%d)\n",
+                      m66592->bi_bufnum);
+               return -ENOMEM;
+       }
+
+       m66592_write(m66592, pipecfg, M66592_PIPECFG);
+       m66592_write(m66592, (buf_bsize << 10) | (bufnum), M66592_PIPEBUF);
+       m66592_write(m66592, info->maxpacket, M66592_PIPEMAXP);
+       if (info->interval)
+               info->interval--;
+       m66592_write(m66592, info->interval, M66592_PIPEPERI);
+
+       return 0;
+}
+
+static void pipe_buffer_release(struct m66592 *m66592,
+                               struct m66592_pipe_info *info)
+{
+       if (info->pipe == 0)
+               return;
+
+       switch (info->type) {
+       case M66592_BULK:
+               if (is_bulk_pipe(info->pipe))
+                       m66592->bi_bufnum -= 16;
+               break;
+       case M66592_ISO:
+               if (is_isoc_pipe(info->pipe))
+                       m66592->bi_bufnum -= 16;
+               break;
+       }
+
+       if (is_bulk_pipe(info->pipe)) {
+               m66592->bulk--;
+       } else if (is_interrupt_pipe(info->pipe))
+               m66592->interrupt--;
+       else if (is_isoc_pipe(info->pipe)) {
+               m66592->isochronous--;
+               if (info->type == M66592_BULK)
+                       m66592->bulk--;
+       } else
+               printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n",
+                      info->pipe);
+}
+
+static void pipe_initialize(struct m66592_ep *ep)
+{
+       struct m66592 *m66592 = ep->m66592;
+
+       m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel);
+
+       m66592_write(m66592, M66592_ACLRM, ep->pipectr);
+       m66592_write(m66592, 0, ep->pipectr);
+       m66592_write(m66592, M66592_SQCLR, ep->pipectr);
+       if (ep->use_dma) {
+               m66592_mdfy(m66592, ep->pipenum, M66592_CURPIPE, ep->fifosel);
+
+               ndelay(450);
+
+               m66592_bset(m66592, M66592_MBW, ep->fifosel);
+       }
+}
+
+static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
+                             const struct usb_endpoint_descriptor *desc,
+                             u16 pipenum, int dma)
+{
+       if ((pipenum != 0) && dma) {
+               if (m66592->num_dma == 0) {
+                       m66592->num_dma++;
+                       ep->use_dma = 1;
+                       ep->fifoaddr = M66592_D0FIFO;
+                       ep->fifosel = M66592_D0FIFOSEL;
+                       ep->fifoctr = M66592_D0FIFOCTR;
+                       ep->fifotrn = M66592_D0FIFOTRN;
+               } else if (m66592->num_dma == 1) {
+                       m66592->num_dma++;
+                       ep->use_dma = 1;
+                       ep->fifoaddr = M66592_D1FIFO;
+                       ep->fifosel = M66592_D1FIFOSEL;
+                       ep->fifoctr = M66592_D1FIFOCTR;
+                       ep->fifotrn = M66592_D1FIFOTRN;
+               } else {
+                       ep->use_dma = 0;
+                       ep->fifoaddr = M66592_CFIFO;
+                       ep->fifosel = M66592_CFIFOSEL;
+                       ep->fifoctr = M66592_CFIFOCTR;
+                       ep->fifotrn = 0;
+               }
+       } else {
+               ep->use_dma = 0;
+               ep->fifoaddr = M66592_CFIFO;
+               ep->fifosel = M66592_CFIFOSEL;
+               ep->fifoctr = M66592_CFIFOCTR;
+               ep->fifotrn = 0;
+       }
+
+       ep->pipectr = get_pipectr_addr(pipenum);
+       ep->pipenum = pipenum;
+       ep->ep.maxpacket = desc->wMaxPacketSize;
+       m66592->pipenum2ep[pipenum] = ep;
+       m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep;
+       INIT_LIST_HEAD(&ep->queue);
+}
+
+static void m66592_ep_release(struct m66592_ep *ep)
+{
+       struct m66592 *m66592 = ep->m66592;
+       u16 pipenum = ep->pipenum;
+
+       if (pipenum == 0)
+               return;
+
+       if (ep->use_dma)
+               m66592->num_dma--;
+       ep->pipenum = 0;
+       ep->busy = 0;
+       ep->use_dma = 0;
+}
+
+static int alloc_pipe_config(struct m66592_ep *ep,
+                            const struct usb_endpoint_descriptor *desc)
+{
+       struct m66592 *m66592 = ep->m66592;
+       struct m66592_pipe_info info;
+       int dma = 0;
+       int *counter;
+       int ret;
+
+       ep->desc = desc;
+
+       BUG_ON(ep->pipenum);
+
+       switch(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_BULK:
+               if (m66592->bulk >= M66592_MAX_NUM_BULK) {
+                       if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
+                               printk(KERN_ERR "bulk pipe is insufficient\n");
+                               return -ENODEV;
+                       } else {
+                               info.pipe = M66592_BASE_PIPENUM_ISOC +
+                                           m66592->isochronous;
+                               counter = &m66592->isochronous;
+                       }
+               } else {
+                       info.pipe = M66592_BASE_PIPENUM_BULK + m66592->bulk;
+                       counter = &m66592->bulk;
+               }
+               info.type = M66592_BULK;
+               dma = 1;
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               if (m66592->interrupt >= M66592_MAX_NUM_INT) {
+                       printk(KERN_ERR "interrupt pipe is insufficient\n");
+                       return -ENODEV;
+               }
+               info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
+               info.type = M66592_INT;
+               counter = &m66592->interrupt;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
+                       printk(KERN_ERR "isochronous pipe is insufficient\n");
+                       return -ENODEV;
+               }
+               info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
+               info.type = M66592_ISO;
+               counter = &m66592->isochronous;
+               break;
+       default:
+               printk(KERN_ERR "unexpect xfer type\n");
+               return -EINVAL;
+       }
+       ep->type = info.type;
+
+       info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+       info.maxpacket = desc->wMaxPacketSize;
+       info.interval = desc->bInterval;
+       if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+               info.dir_in = 1;
+       else
+               info.dir_in = 0;
+
+       ret = pipe_buffer_setting(m66592, &info);
+       if (ret < 0) {
+               printk(KERN_ERR "pipe_buffer_setting fail\n");
+               return ret;
+       }
+
+       (*counter)++;
+       if ((counter == &m66592->isochronous) && info.type == M66592_BULK)
+               m66592->bulk++;
+
+       m66592_ep_setting(m66592, ep, desc, info.pipe, dma);
+       pipe_initialize(ep);
+
+       return 0;
+}
+
+static int free_pipe_config(struct m66592_ep *ep)
+{
+       struct m66592 *m66592 = ep->m66592;
+       struct m66592_pipe_info info;
+
+       info.pipe = ep->pipenum;
+       info.type = ep->type;
+       pipe_buffer_release(m66592, &info);
+       m66592_ep_release(ep);
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static void pipe_irq_enable(struct m66592 *m66592, u16 pipenum)
+{
+       enable_irq_ready(m66592, pipenum);
+       enable_irq_nrdy(m66592, pipenum);
+}
+
+static void pipe_irq_disable(struct m66592 *m66592, u16 pipenum)
+{
+       disable_irq_ready(m66592, pipenum);
+       disable_irq_nrdy(m66592, pipenum);
+}
+
+/* if complete is true, gadget driver complete function is not call */
+static void control_end(struct m66592 *m66592, unsigned ccpl)
+{
+       m66592->ep[0].internal_ccpl = ccpl;
+       pipe_start(m66592, 0);
+       m66592_bset(m66592, M66592_CCPL, M66592_DCPCTR);
+}
+
+static void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+       struct m66592 *m66592 = ep->m66592;
+
+       pipe_change(m66592, ep->pipenum);
+       m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0,
+                   (M66592_ISEL | M66592_CURPIPE),
+                   M66592_CFIFOSEL);
+       m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+       if (req->req.length == 0) {
+               m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+               pipe_start(m66592, 0);
+               transfer_complete(ep, req, 0);
+       } else {
+               m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
+               irq_ep0_write(ep, req);
+       }
+}
+
+static void start_packet_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+       struct m66592 *m66592 = ep->m66592;
+       u16 tmp;
+
+       pipe_change(m66592, ep->pipenum);
+       disable_irq_empty(m66592, ep->pipenum);
+       pipe_start(m66592, ep->pipenum);
+
+       tmp = m66592_read(m66592, ep->fifoctr);
+       if (unlikely((tmp & M66592_FRDY) == 0))
+               pipe_irq_enable(m66592, ep->pipenum);
+       else
+               irq_packet_write(ep, req);
+}
+
+static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
+{
+       struct m66592 *m66592 = ep->m66592;
+       u16 pipenum = ep->pipenum;
+
+       if (ep->pipenum == 0) {
+               m66592_mdfy(m66592, M66592_PIPE0,
+                           (M66592_ISEL | M66592_CURPIPE),
+                           M66592_CFIFOSEL);
+               m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+               pipe_start(m66592, pipenum);
+               pipe_irq_enable(m66592, pipenum);
+       } else {
+               if (ep->use_dma) {
+                       m66592_bset(m66592, M66592_TRCLR, ep->fifosel);
+                       pipe_change(m66592, pipenum);
+                       m66592_bset(m66592, M66592_TRENB, ep->fifosel);
+                       m66592_write(m66592,
+                                    (req->req.length + ep->ep.maxpacket - 1) /
+                                    ep->ep.maxpacket, ep->fifotrn);
+               }
+               pipe_start(m66592, pipenum);    /* trigger once */
+               pipe_irq_enable(m66592, pipenum);
+       }
+}
+
+static void start_packet(struct m66592_ep *ep, struct m66592_request *req)
+{
+       if (ep->desc->bEndpointAddress & USB_DIR_IN)
+               start_packet_write(ep, req);
+       else
+               start_packet_read(ep, req);
+}
+
+static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
+{
+       u16 ctsq;
+
+       ctsq = m66592_read(ep->m66592, M66592_INTSTS0) & M66592_CTSQ;
+
+       switch (ctsq) {
+       case M66592_CS_RDDS:
+               start_ep0_write(ep, req);
+               break;
+       case M66592_CS_WRDS:
+               start_packet_read(ep, req);
+               break;
+
+       case M66592_CS_WRND:
+               control_end(ep->m66592, 0);
+               break;
+       default:
+               printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq);
+               break;
+       }
+}
+
+static void init_controller(struct m66592 *m66592)
+{
+       m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
+                   M66592_PINCFG);
+       m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);         /* High spd */
+       m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG);
+
+       m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+       m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+       m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+
+       m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+
+       msleep(3);
+
+       m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
+
+       msleep(1);
+
+       m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
+
+       m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
+       m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
+                    M66592_DMA0CFG);
+}
+
+static void disable_controller(struct m66592 *m66592)
+{
+       m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
+       udelay(1);
+       m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
+       udelay(1);
+       m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
+       udelay(1);
+       m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
+}
+
+static void m66592_start_xclock(struct m66592 *m66592)
+{
+       u16 tmp;
+
+       tmp = m66592_read(m66592, M66592_SYSCFG);
+       if (!(tmp & M66592_XCKE))
+               m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+}
+
+/*-------------------------------------------------------------------------*/
+static void transfer_complete(struct m66592_ep *ep,
+                             struct m66592_request *req,
+                             int status)
+{
+       int restart = 0;
+
+       if (unlikely(ep->pipenum == 0)) {
+               if (ep->internal_ccpl) {
+                       ep->internal_ccpl = 0;
+                       return;
+               }
+       }
+
+       list_del_init(&req->queue);
+       if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
+               req->req.status = -ESHUTDOWN;
+       else
+               req->req.status = status;
+
+       if (!list_empty(&ep->queue))
+               restart = 1;
+
+       if (likely(req->req.complete))
+               req->req.complete(&ep->ep, &req->req);
+
+       if (restart) {
+               req = list_entry(ep->queue.next, struct m66592_request, queue);
+               if (ep->desc)
+                       start_packet(ep, req);
+       }
+}
+
+static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+       int i;
+       volatile u16 tmp;
+       unsigned bufsize;
+       size_t size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct m66592 *m66592 = ep->m66592;
+
+       pipe_change(m66592, pipenum);
+       m66592_bset(m66592, M66592_ISEL, ep->fifosel);
+
+       i = 0;
+       do {
+               tmp = m66592_read(m66592, ep->fifoctr);
+               if (i++ > 100000) {
+                       printk(KERN_ERR "pipe0 is busy. maybe cpu i/o bus"
+                               "conflict. please power off this controller.");
+                       return;
+               }
+               ndelay(1);
+       } while ((tmp & M66592_FRDY) == 0);
+
+       /* prepare parameters */
+       bufsize = get_buffer_size(m66592, pipenum);
+       buf = req->req.buf + req->req.actual;
+       size = min(bufsize, req->req.length - req->req.actual);
+
+       /* write fifo */
+       if (req->req.buf) {
+               if (size > 0)
+                       m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
+               if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
+                       m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+       }
+
+       /* update parameters */
+       req->req.actual += size;
+
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length)) ||
+           (size % ep->ep.maxpacket) || (size == 0)) {
+               disable_irq_ready(m66592, pipenum);
+               disable_irq_empty(m66592, pipenum);
+       } else {
+               disable_irq_ready(m66592, pipenum);
+               enable_irq_empty(m66592, pipenum);
+       }
+       pipe_start(m66592, pipenum);
+}
+
+static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+       u16 tmp;
+       unsigned bufsize;
+       size_t size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct m66592 *m66592 = ep->m66592;
+
+       pipe_change(m66592, pipenum);
+       tmp = m66592_read(m66592, ep->fifoctr);
+       if (unlikely((tmp & M66592_FRDY) == 0)) {
+               pipe_stop(m66592, pipenum);
+               pipe_irq_disable(m66592, pipenum);
+               printk(KERN_ERR "write fifo not ready. pipnum=%d\n", pipenum);
+               return;
+       }
+
+       /* prepare parameters */
+       bufsize = get_buffer_size(m66592, pipenum);
+       buf = req->req.buf + req->req.actual;
+       size = min(bufsize, req->req.length - req->req.actual);
+
+       /* write fifo */
+       if (req->req.buf) {
+               m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
+               if ((size == 0) || ((size % ep->ep.maxpacket) != 0) ||
+                   ((bufsize != ep->ep.maxpacket) && (bufsize > size)))
+                       m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+       }
+
+       /* update parameters */
+       req->req.actual += size;
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length)) ||
+           (size % ep->ep.maxpacket) || (size == 0)) {
+               disable_irq_ready(m66592, pipenum);
+               enable_irq_empty(m66592, pipenum);
+       } else {
+               disable_irq_empty(m66592, pipenum);
+               pipe_irq_enable(m66592, pipenum);
+       }
+}
+
+static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
+{
+       u16 tmp;
+       int rcv_len, bufsize, req_len;
+       int size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct m66592 *m66592 = ep->m66592;
+       int finish = 0;
+
+       pipe_change(m66592, pipenum);
+       tmp = m66592_read(m66592, ep->fifoctr);
+       if (unlikely((tmp & M66592_FRDY) == 0)) {
+               req->req.status = -EPIPE;
+               pipe_stop(m66592, pipenum);
+               pipe_irq_disable(m66592, pipenum);
+               printk(KERN_ERR "read fifo not ready");
+               return;
+       }
+
+       /* prepare parameters */
+       rcv_len = tmp & M66592_DTLN;
+       bufsize = get_buffer_size(m66592, pipenum);
+
+       buf = req->req.buf + req->req.actual;
+       req_len = req->req.length - req->req.actual;
+       if (rcv_len < bufsize)
+               size = min(rcv_len, req_len);
+       else
+               size = min(bufsize, req_len);
+
+       /* update parameters */
+       req->req.actual += size;
+
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length)) ||
+           (size % ep->ep.maxpacket) || (size == 0)) {
+               pipe_stop(m66592, pipenum);
+               pipe_irq_disable(m66592, pipenum);
+               finish = 1;
+       }
+
+       /* read fifo */
+       if (req->req.buf) {
+               if (size == 0)
+                       m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+               else
+                       m66592_read_fifo(m66592, ep->fifoaddr, buf, size);
+       }
+
+       if ((ep->pipenum != 0) && finish)
+               transfer_complete(ep, req, 0);
+}
+
+static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
+{
+       u16 check;
+       u16 pipenum;
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+
+       if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {
+               m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);
+               m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,
+                           M66592_CFIFOSEL);
+
+               ep = &m66592->ep[0];
+               req = list_entry(ep->queue.next, struct m66592_request, queue);
+               irq_packet_read(ep, req);
+       } else {
+               for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
+                       check = 1 << pipenum;
+                       if ((status & check) && (enb & check)) {
+                               m66592_write(m66592, ~check, M66592_BRDYSTS);
+                               ep = m66592->pipenum2ep[pipenum];
+                               req = list_entry(ep->queue.next,
+                                                struct m66592_request, queue);
+                               if (ep->desc->bEndpointAddress & USB_DIR_IN)
+                                       irq_packet_write(ep, req);
+                               else
+                                       irq_packet_read(ep, req);
+                       }
+               }
+       }
+}
+
+static void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb)
+{
+       u16 tmp;
+       u16 check;
+       u16 pipenum;
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+
+       if ((status & M66592_BEMP0) && (enb & M66592_BEMP0)) {
+               m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
+
+               ep = &m66592->ep[0];
+               req = list_entry(ep->queue.next, struct m66592_request, queue);
+               irq_ep0_write(ep, req);
+       } else {
+               for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
+                       check = 1 << pipenum;
+                       if ((status & check) && (enb & check)) {
+                               m66592_write(m66592, ~check, M66592_BEMPSTS);
+                               tmp = control_reg_get(m66592, pipenum);
+                               if ((tmp & M66592_INBUFM) == 0) {
+                                       disable_irq_empty(m66592, pipenum);
+                                       pipe_irq_disable(m66592, pipenum);
+                                       pipe_stop(m66592, pipenum);
+                                       ep = m66592->pipenum2ep[pipenum];
+                                       req = list_entry(ep->queue.next,
+                                                        struct m66592_request,
+                                                        queue);
+                                       if (!list_empty(&ep->queue))
+                                               transfer_complete(ep, req, 0);
+                               }
+                       }
+               }
+       }
+}
+
+static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+       struct m66592_ep *ep;
+       u16 pid;
+       u16 status = 0;
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               status = 1;     /* selfpower */
+               break;
+       case USB_RECIP_INTERFACE:
+               status = 0;
+               break;
+       case USB_RECIP_ENDPOINT:
+               ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+               pid = control_reg_get_pid(m66592, ep->pipenum);
+               if (pid == M66592_PID_STALL)
+                       status = 1;
+               else
+                       status = 0;
+               break;
+       default:
+               pipe_stall(m66592, 0);
+               return;         /* exit */
+       }
+
+       *m66592->ep0_buf = status;
+       m66592->ep0_req->buf = m66592->ep0_buf;
+       m66592->ep0_req->length = 2;
+       m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);
+}
+
+static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               control_end(m66592, 1);
+               break;
+       case USB_RECIP_INTERFACE:
+               control_end(m66592, 1);
+               break;
+       case USB_RECIP_ENDPOINT: {
+               struct m66592_ep *ep;
+               struct m66592_request *req;
+
+               ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+               pipe_stop(m66592, ep->pipenum);
+               control_reg_sqclr(m66592, ep->pipenum);
+
+               control_end(m66592, 1);
+
+               req = list_entry(ep->queue.next,
+               struct m66592_request, queue);
+               if (ep->busy) {
+                       ep->busy = 0;
+                       if (list_empty(&ep->queue))
+                               break;
+                       start_packet(ep, req);
+               } else if (!list_empty(&ep->queue))
+                       pipe_start(m66592, ep->pipenum);
+               }
+               break;
+       default:
+               pipe_stall(m66592, 0);
+               break;
+       }
+}
+
+static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               control_end(m66592, 1);
+               break;
+       case USB_RECIP_INTERFACE:
+               control_end(m66592, 1);
+               break;
+       case USB_RECIP_ENDPOINT: {
+               struct m66592_ep *ep;
+
+               ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+               pipe_stall(m66592, ep->pipenum);
+
+               control_end(m66592, 1);
+               }
+               break;
+       default:
+               pipe_stall(m66592, 0);
+               break;
+       }
+}
+
+/* if return value is true, call class driver's setup() */
+static int setup_packet(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+       u16 *p = (u16 *)ctrl;
+       unsigned long offset = M66592_USBREQ;
+       int i, ret = 0;
+
+       /* read fifo */
+       m66592_write(m66592, ~M66592_VALID, M66592_INTSTS0);
+
+       for (i = 0; i < 4; i++)
+               p[i] = m66592_read(m66592, offset + i*2);
+
+       /* check request */
+       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+               switch (ctrl->bRequest) {
+               case USB_REQ_GET_STATUS:
+                       get_status(m66592, ctrl);
+                       break;
+               case USB_REQ_CLEAR_FEATURE:
+                       clear_feature(m66592, ctrl);
+                       break;
+               case USB_REQ_SET_FEATURE:
+                       set_feature(m66592, ctrl);
+                       break;
+               default:
+                       ret = 1;
+                       break;
+               }
+       } else
+               ret = 1;
+       return ret;
+}
+
+static void m66592_update_usb_speed(struct m66592 *m66592)
+{
+       u16 speed = get_usb_speed(m66592);
+
+       switch (speed) {
+       case M66592_HSMODE:
+               m66592->gadget.speed = USB_SPEED_HIGH;
+               break;
+       case M66592_FSMODE:
+               m66592->gadget.speed = USB_SPEED_FULL;
+               break;
+       default:
+               m66592->gadget.speed = USB_SPEED_UNKNOWN;
+               printk(KERN_ERR "USB speed unknown\n");
+       }
+}
+
+static void irq_device_state(struct m66592 *m66592)
+{
+       u16 dvsq;
+
+       dvsq = m66592_read(m66592, M66592_INTSTS0) & M66592_DVSQ;
+       m66592_write(m66592, ~M66592_DVST, M66592_INTSTS0);
+
+       if (dvsq == M66592_DS_DFLT) {   /* bus reset */
+               m66592->driver->disconnect(&m66592->gadget);
+               m66592_update_usb_speed(m66592);
+       }
+       if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)
+               m66592_update_usb_speed(m66592);
+       if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS) &&
+           m66592->gadget.speed == USB_SPEED_UNKNOWN)
+               m66592_update_usb_speed(m66592);
+
+       m66592->old_dvsq = dvsq;
+}
+
+static void irq_control_stage(struct m66592 *m66592)
+{
+       struct usb_ctrlrequest ctrl;
+       u16 ctsq;
+
+       ctsq = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ;
+       m66592_write(m66592, ~M66592_CTRT, M66592_INTSTS0);
+
+       switch (ctsq) {
+       case M66592_CS_IDST: {
+               struct m66592_ep *ep;
+               struct m66592_request *req;
+               ep = &m66592->ep[0];
+               req = list_entry(ep->queue.next, struct m66592_request, queue);
+               transfer_complete(ep, req, 0);
+               }
+               break;
+
+       case M66592_CS_RDDS:
+       case M66592_CS_WRDS:
+       case M66592_CS_WRND:
+               if (setup_packet(m66592, &ctrl)) {
+                       if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0)
+                               pipe_stall(m66592, 0);
+               }
+               break;
+       case M66592_CS_RDSS:
+       case M66592_CS_WRSS:
+               control_end(m66592, 0);
+               break;
+       default:
+               printk(KERN_ERR "ctrl_stage: unexpect ctsq(%x)\n", ctsq);
+               break;
+       }
+}
+
+static irqreturn_t m66592_irq(int irq, void *_m66592)
+{
+       struct m66592 *m66592 = _m66592;
+       u16 intsts0;
+       u16 intenb0;
+       u16 brdysts, nrdysts, bempsts;
+       u16 brdyenb, nrdyenb, bempenb;
+       u16 savepipe;
+       u16 mask0;
+
+       intsts0 = m66592_read(m66592, M66592_INTSTS0);
+       intenb0 = m66592_read(m66592, M66592_INTENB0);
+
+       savepipe = m66592_read(m66592, M66592_CFIFOSEL);
+
+       mask0 = intsts0 & intenb0;
+       if (mask0) {
+               brdysts = m66592_read(m66592, M66592_BRDYSTS);
+               nrdysts = m66592_read(m66592, M66592_NRDYSTS);
+               bempsts = m66592_read(m66592, M66592_BEMPSTS);
+               brdyenb = m66592_read(m66592, M66592_BRDYENB);
+               nrdyenb = m66592_read(m66592, M66592_NRDYENB);
+               bempenb = m66592_read(m66592, M66592_BEMPENB);
+
+               if (mask0 & M66592_VBINT) {
+                       m66592_write(m66592, (u16)~M66592_VBINT,
+                                    M66592_INTSTS0);
+                       m66592_start_xclock(m66592);
+
+                       /* start vbus sampling */
+                       m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0)
+                                          & M66592_VBSTS;
+                       m66592->scount = M66592_MAX_SAMPLING;
+
+                       mod_timer(&m66592->timer,
+                                 jiffies + msecs_to_jiffies(50));
+               }
+               if (intsts0 & M66592_DVSQ)
+                       irq_device_state(m66592);
+
+               if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE) &&
+                   (brdysts & brdyenb)) {
+                       irq_pipe_ready(m66592, brdysts, brdyenb);
+               }
+               if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE) &&
+                   (bempsts & bempenb)) {
+                       irq_pipe_empty(m66592, bempsts, bempenb);
+               }
+
+               if (intsts0 & M66592_CTRT)
+                       irq_control_stage(m66592);
+       }
+
+       m66592_write(m66592, savepipe, M66592_CFIFOSEL);
+
+       return IRQ_HANDLED;
+}
+
+static void m66592_timer(unsigned long _m66592)
+{
+       struct m66592 *m66592 = (struct m66592 *)_m66592;
+       unsigned long flags;
+       u16 tmp;
+
+       spin_lock_irqsave(&m66592->lock, flags);
+       tmp = m66592_read(m66592, M66592_SYSCFG);
+       if (!(tmp & M66592_RCKE)) {
+               m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
+               udelay(10);
+               m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
+       }
+       if (m66592->scount > 0) {
+               tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS;
+               if (tmp == m66592->old_vbus) {
+                       m66592->scount--;
+                       if (m66592->scount == 0) {
+                               if (tmp == M66592_VBSTS)
+                                       m66592_usb_connect(m66592);
+                               else
+                                       m66592_usb_disconnect(m66592);
+                       } else {
+                               mod_timer(&m66592->timer,
+                                         jiffies + msecs_to_jiffies(50));
+                       }
+               } else {
+                       m66592->scount = M66592_MAX_SAMPLING;
+                       m66592->old_vbus = tmp;
+                       mod_timer(&m66592->timer,
+                                 jiffies + msecs_to_jiffies(50));
+               }
+       }
+       spin_unlock_irqrestore(&m66592->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+static int m66592_enable(struct usb_ep *_ep,
+                        const struct usb_endpoint_descriptor *desc)
+{
+       struct m66592_ep *ep;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       return alloc_pipe_config(ep, desc);
+}
+
+static int m66592_disable(struct usb_ep *_ep)
+{
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       BUG_ON(!ep);
+
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct m66592_request, queue);
+               spin_lock_irqsave(&ep->m66592->lock, flags);
+               transfer_complete(ep, req, -ECONNRESET);
+               spin_unlock_irqrestore(&ep->m66592->lock, flags);
+       }
+
+       pipe_irq_disable(ep->m66592, ep->pipenum);
+       return free_pipe_config(ep);
+}
+
+static struct usb_request *m66592_alloc_request(struct usb_ep *_ep,
+                                               gfp_t gfp_flags)
+{
+       struct m66592_request *req;
+
+       req = kzalloc(sizeof(struct m66592_request), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void m66592_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct m66592_request *req;
+
+       req = container_of(_req, struct m66592_request, req);
+       kfree(req);
+}
+
+static void *m66592_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
+                                dma_addr_t *dma, gfp_t gfp_flags)
+{
+       void *buf;
+
+       buf = kzalloc(bytes, gfp_flags);
+       if (dma)
+               *dma = virt_to_bus(buf);
+
+       return buf;
+}
+
+static void m66592_free_buffer(struct usb_ep *_ep, void *buf,
+                              dma_addr_t dma, unsigned bytes)
+{
+       kfree(buf);
+}
+
+static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags)
+{
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+       unsigned long flags;
+       int request = 0;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       req = container_of(_req, struct m66592_request, req);
+
+       if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&ep->m66592->lock, flags);
+
+       if (list_empty(&ep->queue))
+               request = 1;
+
+       list_add_tail(&req->queue, &ep->queue);
+       req->req.actual = 0;
+       req->req.status = -EINPROGRESS;
+
+       if (ep->desc == 0)      /* control */
+               start_ep0(ep, req);
+       else {
+               if (request && !ep->busy)
+                       start_packet(ep, req);
+       }
+
+       spin_unlock_irqrestore(&ep->m66592->lock, flags);
+
+       return 0;
+}
+
+static int m66592_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       req = container_of(_req, struct m66592_request, req);
+
+       spin_lock_irqsave(&ep->m66592->lock, flags);
+       if (!list_empty(&ep->queue))
+               transfer_complete(ep, req, -ECONNRESET);
+       spin_unlock_irqrestore(&ep->m66592->lock, flags);
+
+       return 0;
+}
+
+static int m66592_set_halt(struct usb_ep *_ep, int value)
+{
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+       unsigned long flags;
+       int ret = 0;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       req = list_entry(ep->queue.next, struct m66592_request, queue);
+
+       spin_lock_irqsave(&ep->m66592->lock, flags);
+       if (!list_empty(&ep->queue)) {
+               ret = -EAGAIN;
+               goto out;
+       }
+       if (value) {
+               ep->busy = 1;
+               pipe_stall(ep->m66592, ep->pipenum);
+       } else {
+               ep->busy = 0;
+               pipe_stop(ep->m66592, ep->pipenum);
+       }
+
+out:
+       spin_unlock_irqrestore(&ep->m66592->lock, flags);
+       return ret;
+}
+
+static int m66592_fifo_status(struct usb_ep *_ep)
+{
+       return -EOPNOTSUPP;
+}
+
+static void m66592_fifo_flush(struct usb_ep *_ep)
+{
+       struct m66592_ep *ep;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       spin_lock_irqsave(&ep->m66592->lock, flags);
+       if (list_empty(&ep->queue) && !ep->busy) {
+               pipe_stop(ep->m66592, ep->pipenum);
+               m66592_bclr(ep->m66592, M66592_BCLR, ep->fifoctr);
+       }
+       spin_unlock_irqrestore(&ep->m66592->lock, flags);
+}
+
+static struct usb_ep_ops m66592_ep_ops = {
+       .enable         = m66592_enable,
+       .disable        = m66592_disable,
+
+       .alloc_request  = m66592_alloc_request,
+       .free_request   = m66592_free_request,
+
+       .alloc_buffer   = m66592_alloc_buffer,
+       .free_buffer    = m66592_free_buffer,
+
+       .queue          = m66592_queue,
+       .dequeue        = m66592_dequeue,
+
+       .set_halt       = m66592_set_halt,
+       .fifo_status    = m66592_fifo_status,
+       .fifo_flush     = m66592_fifo_flush,
+};
+
+/*-------------------------------------------------------------------------*/
+static struct m66592 *the_controller;
+
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+       struct m66592 *m66592 = the_controller;
+       int retval;
+
+       if (!driver ||
+           driver->speed != USB_SPEED_HIGH ||
+           !driver->bind ||
+           !driver->unbind ||
+           !driver->setup)
+               return -EINVAL;
+       if (!m66592)
+               return -ENODEV;
+       if (m66592->driver)
+               return -EBUSY;
+
+       /* hook up the driver */
+       driver->driver.bus = NULL;
+       m66592->driver = driver;
+       m66592->gadget.dev.driver = &driver->driver;
+
+       retval = device_add(&m66592->gadget.dev);
+       if (retval) {
+               printk(KERN_ERR "device_add error (%d)\n", retval);
+               goto error;
+       }
+
+       retval = driver->bind (&m66592->gadget);
+       if (retval) {
+               printk(KERN_ERR "bind to driver error (%d)\n", retval);
+               device_del(&m66592->gadget.dev);
+               goto error;
+       }
+
+       m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
+       if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
+               m66592_start_xclock(m66592);
+               /* start vbus sampling */
+               m66592->old_vbus = m66592_read(m66592,
+                                        M66592_INTSTS0) & M66592_VBSTS;
+               m66592->scount = M66592_MAX_SAMPLING;
+               mod_timer(&m66592->timer,
+                         jiffies + msecs_to_jiffies(50));
+       }
+
+       return 0;
+
+error:
+       m66592->driver = NULL;
+       m66592->gadget.dev.driver = NULL;
+
+       return retval;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+       struct m66592 *m66592 = the_controller;
+       unsigned long flags;
+
+       spin_lock_irqsave(&m66592->lock, flags);
+       if (m66592->gadget.speed != USB_SPEED_UNKNOWN)
+               m66592_usb_disconnect(m66592);
+       spin_unlock_irqrestore(&m66592->lock, flags);
+
+       m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
+
+       driver->unbind(&m66592->gadget);
+
+       init_controller(m66592);
+       disable_controller(m66592);
+
+       device_del(&m66592->gadget.dev);
+       m66592->driver = NULL;
+       return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/*-------------------------------------------------------------------------*/
+static int m66592_get_frame(struct usb_gadget *_gadget)
+{
+       struct m66592 *m66592 = gadget_to_m66592(_gadget);
+       return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
+}
+
+static struct usb_gadget_ops m66592_gadget_ops = {
+       .get_frame              = m66592_get_frame,
+};
+
+#if defined(CONFIG_PM)
+static int m66592_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       pdev->dev.power.power_state = state;
+       return 0;
+}
+
+static int m66592_resume(struct platform_device *pdev)
+{
+       pdev->dev.power.power_state = PMSG_ON;
+       return 0;
+}
+#else  /* if defined(CONFIG_PM) */
+#define m66592_suspend         NULL
+#define m66592_resume          NULL
+#endif
+
+static int __init_or_module m66592_remove(struct platform_device *pdev)
+{
+       struct m66592           *m66592 = dev_get_drvdata(&pdev->dev);
+
+       del_timer_sync(&m66592->timer);
+       iounmap(m66592->reg);
+       free_irq(platform_get_irq(pdev, 0), m66592);
+       kfree(m66592);
+       return 0;
+}
+
+#define resource_len(r) (((r)->end - (r)->start) + 1)
+static int __init m66592_probe(struct platform_device *pdev)
+{
+       struct resource *res = NULL;
+       int irq = -1;
+       void __iomem *reg = NULL;
+       struct m66592 *m66592 = NULL;
+       int ret = 0;
+       int i;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                          (char *)udc_name);
+       if (!res) {
+               ret = -ENODEV;
+               printk(KERN_ERR "platform_get_resource_byname error.\n");
+               goto clean_up;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               ret = -ENODEV;
+               printk(KERN_ERR "platform_get_irq error.\n");
+               goto clean_up;
+       }
+
+       reg = ioremap(res->start, resource_len(res));
+       if (reg == NULL) {
+               ret = -ENOMEM;
+               printk(KERN_ERR "ioremap error.\n");
+               goto clean_up;
+       }
+
+       /* initialize ucd */
+       m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
+       if (m66592 == NULL) {
+               printk(KERN_ERR "kzalloc error\n");
+               goto clean_up;
+       }
+
+       spin_lock_init(&m66592->lock);
+       dev_set_drvdata(&pdev->dev, m66592);
+
+       m66592->gadget.ops = &m66592_gadget_ops;
+       device_initialize(&m66592->gadget.dev);
+       strcpy(m66592->gadget.dev.bus_id, "gadget");
+       m66592->gadget.is_dualspeed = 1;
+       m66592->gadget.dev.parent = &pdev->dev;
+       m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
+       m66592->gadget.dev.release = pdev->dev.release;
+       m66592->gadget.name = udc_name;
+
+       init_timer(&m66592->timer);
+       m66592->timer.function = m66592_timer;
+       m66592->timer.data = (unsigned long)m66592;
+       m66592->reg = reg;
+
+       m66592->bi_bufnum = M66592_BASE_BUFNUM;
+
+       ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
+                         udc_name, m66592);
+       if (ret < 0) {
+               printk(KERN_ERR "request_irq error (%d)\n", ret);
+               goto clean_up;
+       }
+
+       INIT_LIST_HEAD(&m66592->gadget.ep_list);
+       m66592->gadget.ep0 = &m66592->ep[0].ep;
+       INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list);
+       for (i = 0; i < M66592_MAX_NUM_PIPE; i++) {
+               struct m66592_ep *ep = &m66592->ep[i];
+
+               if (i != 0) {
+                       INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list);
+                       list_add_tail(&m66592->ep[i].ep.ep_list,
+                                     &m66592->gadget.ep_list);
+               }
+               ep->m66592 = m66592;
+               INIT_LIST_HEAD(&ep->queue);
+               ep->ep.name = m66592_ep_name[i];
+               ep->ep.ops = &m66592_ep_ops;
+               ep->ep.maxpacket = 512;
+       }
+       m66592->ep[0].ep.maxpacket = 64;
+       m66592->ep[0].pipenum = 0;
+       m66592->ep[0].fifoaddr = M66592_CFIFO;
+       m66592->ep[0].fifosel = M66592_CFIFOSEL;
+       m66592->ep[0].fifoctr = M66592_CFIFOCTR;
+       m66592->ep[0].fifotrn = 0;
+       m66592->ep[0].pipectr = get_pipectr_addr(0);
+       m66592->pipenum2ep[0] = &m66592->ep[0];
+       m66592->epaddr2ep[0] = &m66592->ep[0];
+
+       the_controller = m66592;
+
+       m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
+       if (m66592->ep0_req == NULL)
+               goto clean_up;
+       m66592->ep0_buf = m66592_alloc_buffer(&m66592->ep[0].ep, 2, NULL,
+                                             GFP_KERNEL);
+       if (m66592->ep0_buf == NULL)
+               goto clean_up;
+
+       init_controller(m66592);
+
+       printk("driver %s, %s\n", udc_name, DRIVER_VERSION);
+       return 0;
+
+clean_up:
+       if (m66592) {
+               if (m66592->ep0_req)
+                       m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+               kfree(m66592);
+       }
+       if (reg)
+               iounmap(reg);
+
+       return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+static struct platform_driver m66592_driver = {
+       .probe =        m66592_probe,
+       .remove =       m66592_remove,
+       .suspend =      m66592_suspend,
+       .resume =       m66592_resume,
+       .driver         = {
+               .name = (char *) udc_name,
+       },
+};
+
+static int __init m66592_udc_init(void)
+{
+       return platform_driver_register(&m66592_driver);
+}
+module_init(m66592_udc_init);
+
+static void __exit m66592_udc_cleanup(void)
+{
+       platform_driver_unregister(&m66592_driver);
+}
+module_exit(m66592_udc_cleanup);
+
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
new file mode 100644 (file)
index 0000000..26b54f8
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+ * M66592 UDC (USB gadget)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __M66592_UDC_H__
+#define __M66592_UDC_H__
+
+#define M66592_SYSCFG          0x00
+#define        M66592_XTAL             0xC000  /* b15-14: Crystal selection */
+#define          M66592_XTAL48          0x8000           /* 48MHz */
+#define   M66592_XTAL24                 0x4000           /* 24MHz */
+#define          M66592_XTAL12          0x0000           /* 12MHz */
+#define        M66592_XCKE             0x2000  /* b13: External clock enable */
+#define        M66592_RCKE             0x1000  /* b12: Register clock enable */
+#define        M66592_PLLC             0x0800  /* b11: PLL control */
+#define        M66592_SCKE             0x0400  /* b10: USB clock enable */
+#define        M66592_ATCKM            0x0100  /* b8: Automatic supply functional enable */
+#define        M66592_HSE              0x0080  /* b7: Hi-speed enable */
+#define        M66592_DCFM             0x0040  /* b6: Controller function select  */
+#define        M66592_DMRPD            0x0020  /* b5: D- pull down control */
+#define        M66592_DPRPU            0x0010  /* b4: D+ pull up control */
+#define        M66592_FSRPC            0x0004  /* b2: Full-speed receiver enable */
+#define        M66592_PCUT             0x0002  /* b1: Low power sleep enable */
+#define        M66592_USBE             0x0001  /* b0: USB module operation enable */
+
+#define M66592_SYSSTS          0x02
+#define        M66592_LNST             0x0003  /* b1-0: D+, D- line status */
+#define          M66592_SE1             0x0003           /* SE1 */
+#define          M66592_KSTS            0x0002           /* K State */
+#define          M66592_JSTS            0x0001           /* J State */
+#define          M66592_SE0             0x0000           /* SE0 */
+
+#define M66592_DVSTCTR         0x04
+#define        M66592_WKUP             0x0100  /* b8: Remote wakeup */
+#define        M66592_RWUPE            0x0080  /* b7: Remote wakeup sense */
+#define        M66592_USBRST           0x0040  /* b6: USB reset enable */
+#define        M66592_RESUME           0x0020  /* b5: Resume enable */
+#define        M66592_UACT             0x0010  /* b4: USB bus enable */
+#define        M66592_RHST             0x0003  /* b1-0: Reset handshake status */
+#define          M66592_HSMODE          0x0003           /* Hi-Speed mode */
+#define          M66592_FSMODE          0x0002           /* Full-Speed mode */
+#define          M66592_HSPROC          0x0001           /* HS handshake is processing */
+
+#define M66592_TESTMODE                0x06
+#define        M66592_UTST             0x000F  /* b4-0: Test select */
+#define          M66592_H_TST_PACKET    0x000C           /* HOST TEST Packet */
+#define          M66592_H_TST_SE0_NAK   0x000B           /* HOST TEST SE0 NAK */
+#define          M66592_H_TST_K         0x000A           /* HOST TEST K */
+#define          M66592_H_TST_J         0x0009           /* HOST TEST J */
+#define          M66592_H_TST_NORMAL    0x0000           /* HOST Normal Mode */
+#define          M66592_P_TST_PACKET    0x0004           /* PERI TEST Packet */
+#define          M66592_P_TST_SE0_NAK   0x0003           /* PERI TEST SE0 NAK */
+#define          M66592_P_TST_K         0x0002           /* PERI TEST K */
+#define          M66592_P_TST_J         0x0001           /* PERI TEST J */
+#define          M66592_P_TST_NORMAL    0x0000           /* PERI Normal Mode */
+
+#define M66592_PINCFG          0x0A
+#define        M66592_LDRV             0x8000  /* b15: Drive Current Adjust */
+#define        M66592_BIGEND           0x0100  /* b8: Big endian mode */
+
+#define M66592_DMA0CFG         0x0C
+#define M66592_DMA1CFG         0x0E
+#define        M66592_DREQA            0x4000  /* b14: Dreq active select */
+#define        M66592_BURST            0x2000  /* b13: Burst mode */
+#define        M66592_DACKA            0x0400  /* b10: Dack active select */
+#define        M66592_DFORM            0x0380  /* b9-7: DMA mode select */
+#define          M66592_CPU_ADR_RD_WR   0x0000           /* Address + RD/WR mode (CPU bus) */
+#define          M66592_CPU_DACK_RD_WR  0x0100           /* DACK + RD/WR mode (CPU bus) */
+#define          M66592_CPU_DACK_ONLY   0x0180           /* DACK only mode (CPU bus) */
+#define          M66592_SPLIT_DACK_ONLY         0x0200           /* DACK only mode (SPLIT bus) */
+#define          M66592_SPLIT_DACK_DSTB         0x0300           /* DACK + DSTB0 mode (SPLIT bus) */
+#define        M66592_DENDA            0x0040  /* b6: Dend active select */
+#define        M66592_PKTM             0x0020  /* b5: Packet mode */
+#define        M66592_DENDE            0x0010  /* b4: Dend enable */
+#define        M66592_OBUS             0x0004  /* b2: OUTbus mode */
+
+#define M66592_CFIFO           0x10
+#define M66592_D0FIFO          0x14
+#define M66592_D1FIFO          0x18
+
+#define M66592_CFIFOSEL                0x1E
+#define M66592_D0FIFOSEL       0x24
+#define M66592_D1FIFOSEL       0x2A
+#define        M66592_RCNT             0x8000  /* b15: Read count mode */
+#define        M66592_REW              0x4000  /* b14: Buffer rewind */
+#define        M66592_DCLRM            0x2000  /* b13: DMA buffer clear mode */
+#define        M66592_DREQE            0x1000  /* b12: DREQ output enable */
+#define        M66592_MBW              0x0400  /* b10: Maximum bit width for FIFO access */
+#define          M66592_MBW_8           0x0000   /*  8bit */
+#define          M66592_MBW_16          0x0400           /* 16bit */
+#define        M66592_TRENB            0x0200  /* b9: Transaction counter enable */
+#define        M66592_TRCLR            0x0100  /* b8: Transaction counter clear */
+#define        M66592_DEZPM            0x0080  /* b7: Zero-length packet additional mode */
+#define        M66592_ISEL             0x0020  /* b5: DCP FIFO port direction select */
+#define        M66592_CURPIPE          0x0007  /* b2-0: PIPE select */
+
+#define M66592_CFIFOCTR                0x20
+#define M66592_D0FIFOCTR       0x26
+#define M66592_D1FIFOCTR       0x2c
+#define        M66592_BVAL             0x8000  /* b15: Buffer valid flag */
+#define        M66592_BCLR             0x4000  /* b14: Buffer clear */
+#define        M66592_FRDY             0x2000  /* b13: FIFO ready */
+#define        M66592_DTLN             0x0FFF  /* b11-0: FIFO received data length */
+
+#define M66592_CFIFOSIE                0x22
+#define        M66592_TGL              0x8000  /* b15: Buffer toggle */
+#define        M66592_SCLR             0x4000  /* b14: Buffer clear */
+#define        M66592_SBUSY            0x2000  /* b13: SIE_FIFO busy */
+
+#define M66592_D0FIFOTRN       0x28
+#define M66592_D1FIFOTRN       0x2E
+#define        M66592_TRNCNT           0xFFFF  /* b15-0: Transaction counter */
+
+#define M66592_INTENB0 0x30
+#define        M66592_VBSE     0x8000  /* b15: VBUS interrupt */
+#define        M66592_RSME     0x4000  /* b14: Resume interrupt */
+#define        M66592_SOFE     0x2000  /* b13: Frame update interrupt */
+#define        M66592_DVSE     0x1000  /* b12: Device state transition interrupt */
+#define        M66592_CTRE     0x0800  /* b11: Control transfer stage transition interrupt */
+#define        M66592_BEMPE    0x0400  /* b10: Buffer empty interrupt */
+#define        M66592_NRDYE    0x0200  /* b9: Buffer not ready interrupt */
+#define        M66592_BRDYE    0x0100  /* b8: Buffer ready interrupt */
+#define        M66592_URST     0x0080  /* b7: USB reset detected interrupt */
+#define        M66592_SADR     0x0040  /* b6: Set address executed interrupt */
+#define        M66592_SCFG     0x0020  /* b5: Set configuration executed interrupt */
+#define        M66592_SUSP     0x0010  /* b4: Suspend detected interrupt */
+#define        M66592_WDST     0x0008  /* b3: Control write data stage completed interrupt */
+#define        M66592_RDST     0x0004  /* b2: Control read data stage completed interrupt */
+#define        M66592_CMPL     0x0002  /* b1: Control transfer complete interrupt */
+#define        M66592_SERR     0x0001  /* b0: Sequence error interrupt */
+
+#define M66592_INTENB1 0x32
+#define        M66592_BCHGE    0x4000  /* b14: USB us chenge interrupt */
+#define        M66592_DTCHE    0x1000  /* b12: Detach sense interrupt */
+#define        M66592_SIGNE    0x0020  /* b5: SETUP IGNORE interrupt */
+#define        M66592_SACKE    0x0010  /* b4: SETUP ACK interrupt */
+#define        M66592_BRDYM    0x0004  /* b2: BRDY clear timing */
+#define        M66592_INTL     0x0002  /* b1: Interrupt sense select */
+#define        M66592_PCSE     0x0001  /* b0: PCUT enable by CS assert */
+
+#define M66592_BRDYENB         0x36
+#define M66592_BRDYSTS         0x46
+#define        M66592_BRDY7            0x0080  /* b7: PIPE7 */
+#define        M66592_BRDY6            0x0040  /* b6: PIPE6 */
+#define        M66592_BRDY5            0x0020  /* b5: PIPE5 */
+#define        M66592_BRDY4            0x0010  /* b4: PIPE4 */
+#define        M66592_BRDY3            0x0008  /* b3: PIPE3 */
+#define        M66592_BRDY2            0x0004  /* b2: PIPE2 */
+#define        M66592_BRDY1            0x0002  /* b1: PIPE1 */
+#define        M66592_BRDY0            0x0001  /* b1: PIPE0 */
+
+#define M66592_NRDYENB         0x38
+#define M66592_NRDYSTS         0x48
+#define        M66592_NRDY7            0x0080  /* b7: PIPE7 */
+#define        M66592_NRDY6            0x0040  /* b6: PIPE6 */
+#define        M66592_NRDY5            0x0020  /* b5: PIPE5 */
+#define        M66592_NRDY4            0x0010  /* b4: PIPE4 */
+#define        M66592_NRDY3            0x0008  /* b3: PIPE3 */
+#define        M66592_NRDY2            0x0004  /* b2: PIPE2 */
+#define        M66592_NRDY1            0x0002  /* b1: PIPE1 */
+#define        M66592_NRDY0            0x0001  /* b1: PIPE0 */
+
+#define M66592_BEMPENB         0x3A
+#define M66592_BEMPSTS         0x4A
+#define        M66592_BEMP7            0x0080  /* b7: PIPE7 */
+#define        M66592_BEMP6            0x0040  /* b6: PIPE6 */
+#define        M66592_BEMP5            0x0020  /* b5: PIPE5 */
+#define        M66592_BEMP4            0x0010  /* b4: PIPE4 */
+#define        M66592_BEMP3            0x0008  /* b3: PIPE3 */
+#define        M66592_BEMP2            0x0004  /* b2: PIPE2 */
+#define        M66592_BEMP1            0x0002  /* b1: PIPE1 */
+#define        M66592_BEMP0            0x0001  /* b0: PIPE0 */
+
+#define M66592_SOFCFG          0x3C
+#define        M66592_SOFM             0x000C  /* b3-2: SOF palse mode */
+#define          M66592_SOF_125US       0x0008           /* SOF OUT 125us uFrame Signal */
+#define          M66592_SOF_1MS         0x0004           /* SOF OUT 1ms Frame Signal */
+#define          M66592_SOF_DISABLE     0x0000           /* SOF OUT Disable */
+
+#define M66592_INTSTS0         0x40
+#define        M66592_VBINT            0x8000  /* b15: VBUS interrupt */
+#define        M66592_RESM             0x4000  /* b14: Resume interrupt */
+#define        M66592_SOFR             0x2000  /* b13: SOF frame update interrupt */
+#define        M66592_DVST             0x1000  /* b12: Device state transition interrupt */
+#define        M66592_CTRT             0x0800  /* b11: Control transfer stage transition interrupt */
+#define        M66592_BEMP             0x0400  /* b10: Buffer empty interrupt */
+#define        M66592_NRDY             0x0200  /* b9: Buffer not ready interrupt */
+#define        M66592_BRDY             0x0100  /* b8: Buffer ready interrupt */
+#define        M66592_VBSTS            0x0080  /* b7: VBUS input port */
+#define        M66592_DVSQ             0x0070  /* b6-4: Device state */
+#define          M66592_DS_SPD_CNFG     0x0070           /* Suspend Configured */
+#define          M66592_DS_SPD_ADDR     0x0060           /* Suspend Address */
+#define          M66592_DS_SPD_DFLT     0x0050           /* Suspend Default */
+#define          M66592_DS_SPD_POWR     0x0040           /* Suspend Powered */
+#define          M66592_DS_SUSP         0x0040           /* Suspend */
+#define          M66592_DS_CNFG         0x0030           /* Configured */
+#define          M66592_DS_ADDS         0x0020           /* Address */
+#define          M66592_DS_DFLT         0x0010           /* Default */
+#define          M66592_DS_POWR         0x0000           /* Powered */
+#define        M66592_DVSQS            0x0030  /* b5-4: Device state */
+#define        M66592_VALID            0x0008  /* b3: Setup packet detected flag */
+#define        M66592_CTSQ             0x0007  /* b2-0: Control transfer stage */
+#define          M66592_CS_SQER         0x0006           /* Sequence error */
+#define          M66592_CS_WRND         0x0005           /* Control write nodata status stage */
+#define          M66592_CS_WRSS         0x0004           /* Control write status stage */
+#define          M66592_CS_WRDS         0x0003           /* Control write data stage */
+#define          M66592_CS_RDSS         0x0002           /* Control read status stage */
+#define          M66592_CS_RDDS         0x0001           /* Control read data stage */
+#define          M66592_CS_IDST         0x0000           /* Idle or setup stage */
+
+#define M66592_INTSTS1         0x42
+#define        M66592_BCHG             0x4000  /* b14: USB bus chenge interrupt */
+#define        M66592_DTCH             0x1000  /* b12: Detach sense interrupt */
+#define        M66592_SIGN             0x0020  /* b5: SETUP IGNORE interrupt */
+#define        M66592_SACK             0x0010  /* b4: SETUP ACK interrupt */
+
+#define M66592_FRMNUM          0x4C
+#define        M66592_OVRN             0x8000  /* b15: Overrun error */
+#define        M66592_CRCE             0x4000  /* b14: Received data error */
+#define        M66592_SOFRM            0x0800  /* b11: SOF output mode */
+#define        M66592_FRNM             0x07FF  /* b10-0: Frame number */
+
+#define M66592_UFRMNUM         0x4E
+#define        M66592_UFRNM            0x0007  /* b2-0: Micro frame number */
+
+#define M66592_RECOVER         0x50
+#define        M66592_STSRECOV         0x0700  /* Status recovery */
+#define          M66592_STSR_HI         0x0400           /* FULL(0) or HI(1) Speed */
+#define          M66592_STSR_DEFAULT    0x0100           /* Default state */
+#define          M66592_STSR_ADDRESS    0x0200           /* Address state */
+#define          M66592_STSR_CONFIG     0x0300           /* Configured state */
+#define        M66592_USBADDR          0x007F  /* b6-0: USB address */
+
+#define M66592_USBREQ                  0x54
+#define        M66592_bRequest                 0xFF00  /* b15-8: bRequest */
+#define          M66592_GET_STATUS              0x0000
+#define          M66592_CLEAR_FEATURE           0x0100
+#define          M66592_ReqRESERVED             0x0200
+#define          M66592_SET_FEATURE             0x0300
+#define          M66592_ReqRESERVED1            0x0400
+#define          M66592_SET_ADDRESS             0x0500
+#define          M66592_GET_DESCRIPTOR          0x0600
+#define          M66592_SET_DESCRIPTOR          0x0700
+#define          M66592_GET_CONFIGURATION       0x0800
+#define          M66592_SET_CONFIGURATION       0x0900
+#define          M66592_GET_INTERFACE           0x0A00
+#define          M66592_SET_INTERFACE           0x0B00
+#define          M66592_SYNCH_FRAME             0x0C00
+#define        M66592_bmRequestType            0x00FF  /* b7-0: bmRequestType */
+#define        M66592_bmRequestTypeDir         0x0080  /* b7  : Data transfer direction */
+#define          M66592_HOST_TO_DEVICE          0x0000
+#define          M66592_DEVICE_TO_HOST          0x0080
+#define        M66592_bmRequestTypeType        0x0060  /* b6-5: Type */
+#define          M66592_STANDARD                0x0000
+#define          M66592_CLASS                   0x0020
+#define          M66592_VENDOR                  0x0040
+#define        M66592_bmRequestTypeRecip       0x001F  /* b4-0: Recipient */
+#define          M66592_DEVICE                  0x0000
+#define          M66592_INTERFACE               0x0001
+#define          M66592_ENDPOINT                0x0002
+
+#define M66592_USBVAL                          0x56
+#define        M66592_wValue                           0xFFFF  /* b15-0: wValue */
+/* Standard Feature Selector */
+#define          M66592_ENDPOINT_HALT                  0x0000
+#define          M66592_DEVICE_REMOTE_WAKEUP           0x0001
+#define          M66592_TEST_MODE                      0x0002
+/* Descriptor Types */
+#define        M66592_DT_TYPE                          0xFF00
+#define        M66592_GET_DT_TYPE(v)                   (((v) & DT_TYPE) >> 8)
+#define          M66592_DT_DEVICE                      0x01
+#define          M66592_DT_CONFIGURATION               0x02
+#define          M66592_DT_STRING                      0x03
+#define          M66592_DT_INTERFACE                   0x04
+#define          M66592_DT_ENDPOINT                    0x05
+#define          M66592_DT_DEVICE_QUALIFIER            0x06
+#define          M66592_DT_OTHER_SPEED_CONFIGURATION   0x07
+#define          M66592_DT_INTERFACE_POWER             0x08
+#define        M66592_DT_INDEX                         0x00FF
+#define        M66592_CONF_NUM                         0x00FF
+#define        M66592_ALT_SET                          0x00FF
+
+#define M66592_USBINDEX                        0x58
+#define        M66592_wIndex                   0xFFFF  /* b15-0: wIndex */
+#define        M66592_TEST_SELECT              0xFF00  /* b15-b8: Test Mode Selectors */
+#define          M66592_TEST_J                  0x0100           /* Test_J */
+#define          M66592_TEST_K                  0x0200           /* Test_K */
+#define          M66592_TEST_SE0_NAK            0x0300           /* Test_SE0_NAK */
+#define          M66592_TEST_PACKET             0x0400           /* Test_Packet */
+#define          M66592_TEST_FORCE_ENABLE       0x0500           /* Test_Force_Enable */
+#define          M66592_TEST_STSelectors        0x0600           /* Standard test selectors */
+#define          M66592_TEST_Reserved           0x4000           /* Reserved */
+#define          M66592_TEST_VSTModes           0xC000           /* Vendor-specific test modes */
+#define        M66592_EP_DIR                   0x0080  /* b7: Endpoint Direction */
+#define          M66592_EP_DIR_IN               0x0080
+#define          M66592_EP_DIR_OUT              0x0000
+
+#define M66592_USBLENG         0x5A
+#define        M66592_wLength          0xFFFF  /* b15-0: wLength */
+
+#define M66592_DCPCFG          0x5C
+#define        M66592_CNTMD            0x0100  /* b8: Continuous transfer mode select */
+#define        M66592_DIR              0x0010  /* b4: Control transfer DIR select */
+
+#define M66592_DCPMAXP         0x5E
+#define        M66592_DEVSEL           0xC000  /* b15-14: Device address select */
+#define          M66592_DEVICE_0        0x0000           /* Device address 0 */
+#define          M66592_DEVICE_1        0x4000           /* Device address 1 */
+#define          M66592_DEVICE_2        0x8000           /* Device address 2 */
+#define          M66592_DEVICE_3        0xC000           /* Device address 3 */
+#define        M66592_MAXP             0x007F  /* b6-0: Maxpacket size of default control pipe */
+
+#define M66592_DCPCTR          0x60
+#define        M66592_BSTS             0x8000  /* b15: Buffer status */
+#define        M66592_SUREQ            0x4000  /* b14: Send USB request  */
+#define        M66592_SQCLR            0x0100  /* b8: Sequence toggle bit clear */
+#define        M66592_SQSET            0x0080  /* b7: Sequence toggle bit set */
+#define        M66592_SQMON            0x0040  /* b6: Sequence toggle bit monitor */
+#define        M66592_CCPL             0x0004  /* b2: Enable control transfer complete */
+#define        M66592_PID              0x0003  /* b1-0: Response PID */
+#define          M66592_PID_STALL       0x0002           /* STALL */
+#define          M66592_PID_BUF         0x0001           /* BUF */
+#define          M66592_PID_NAK         0x0000           /* NAK */
+
+#define M66592_PIPESEL         0x64
+#define        M66592_PIPENM           0x0007  /* b2-0: Pipe select */
+#define          M66592_PIPE0           0x0000           /* PIPE 0 */
+#define          M66592_PIPE1           0x0001           /* PIPE 1 */
+#define          M66592_PIPE2           0x0002           /* PIPE 2 */
+#define          M66592_PIPE3           0x0003           /* PIPE 3 */
+#define          M66592_PIPE4           0x0004           /* PIPE 4 */
+#define          M66592_PIPE5           0x0005           /* PIPE 5 */
+#define          M66592_PIPE6           0x0006           /* PIPE 6 */
+#define          M66592_PIPE7           0x0007           /* PIPE 7 */
+
+#define M66592_PIPECFG         0x66
+#define        M66592_TYP              0xC000  /* b15-14: Transfer type */
+#define          M66592_ISO             0xC000           /* Isochronous */
+#define          M66592_INT             0x8000           /* Interrupt */
+#define          M66592_BULK            0x4000           /* Bulk */
+#define        M66592_BFRE             0x0400  /* b10: Buffer ready interrupt mode select */
+#define        M66592_DBLB             0x0200  /* b9: Double buffer mode select */
+#define        M66592_CNTMD            0x0100  /* b8: Continuous transfer mode select */
+#define        M66592_SHTNAK           0x0080  /* b7: Transfer end NAK */
+#define        M66592_DIR              0x0010  /* b4: Transfer direction select */
+#define          M66592_DIR_H_OUT       0x0010           /* HOST OUT */
+#define          M66592_DIR_P_IN        0x0010           /* PERI IN */
+#define          M66592_DIR_H_IN        0x0000           /* HOST IN */
+#define          M66592_DIR_P_OUT       0x0000           /* PERI OUT */
+#define        M66592_EPNUM            0x000F  /* b3-0: Eendpoint number select */
+#define          M66592_EP1             0x0001
+#define          M66592_EP2             0x0002
+#define          M66592_EP3             0x0003
+#define          M66592_EP4             0x0004
+#define          M66592_EP5             0x0005
+#define          M66592_EP6             0x0006
+#define          M66592_EP7             0x0007
+#define          M66592_EP8             0x0008
+#define          M66592_EP9             0x0009
+#define          M66592_EP10            0x000A
+#define          M66592_EP11            0x000B
+#define          M66592_EP12            0x000C
+#define          M66592_EP13            0x000D
+#define          M66592_EP14            0x000E
+#define          M66592_EP15            0x000F
+
+#define M66592_PIPEBUF         0x68
+#define        M66592_BUFSIZE          0x7C00  /* b14-10: Pipe buffer size */
+#define        M66592_BUF_SIZE(x)      ((((x) / 64) - 1) << 10)
+#define        M66592_BUFNMB           0x00FF  /* b7-0: Pipe buffer number */
+
+#define M66592_PIPEMAXP                0x6A
+#define        M66592_MXPS             0x07FF  /* b10-0: Maxpacket size */
+
+#define M66592_PIPEPERI                0x6C
+#define        M66592_IFIS             0x1000  /* b12: Isochronous in-buffer flush mode select */
+#define        M66592_IITV             0x0007  /* b2-0: Isochronous interval */
+
+#define M66592_PIPE1CTR                0x70
+#define M66592_PIPE2CTR                0x72
+#define M66592_PIPE3CTR                0x74
+#define M66592_PIPE4CTR                0x76
+#define M66592_PIPE5CTR                0x78
+#define M66592_PIPE6CTR                0x7A
+#define M66592_PIPE7CTR                0x7C
+#define        M66592_BSTS             0x8000  /* b15: Buffer status */
+#define        M66592_INBUFM           0x4000  /* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define        M66592_ACLRM            0x0200  /* b9: Out buffer auto clear mode */
+#define        M66592_SQCLR            0x0100  /* b8: Sequence toggle bit clear */
+#define        M66592_SQSET            0x0080  /* b7: Sequence toggle bit set */
+#define        M66592_SQMON            0x0040  /* b6: Sequence toggle bit monitor */
+#define        M66592_PID              0x0003  /* b1-0: Response PID */
+
+#define M66592_INVALID_REG     0x7E
+
+
+#define __iomem
+
+#define get_pipectr_addr(pipenum)      (M66592_PIPE1CTR + (pipenum - 1) * 2)
+
+#define M66592_MAX_SAMPLING    10
+
+#define M66592_MAX_NUM_PIPE    8
+#define M66592_MAX_NUM_BULK    3
+#define M66592_MAX_NUM_ISOC    2
+#define M66592_MAX_NUM_INT     2
+
+#define M66592_BASE_PIPENUM_BULK       3
+#define M66592_BASE_PIPENUM_ISOC       1
+#define M66592_BASE_PIPENUM_INT                6
+
+#define M66592_BASE_BUFNUM     6
+#define M66592_MAX_BUFNUM      0x4F
+
+struct m66592_pipe_info {
+       u16     pipe;
+       u16     epnum;
+       u16     maxpacket;
+       u16     type;
+       u16     interval;
+       u16     dir_in;
+};
+
+struct m66592_request {
+       struct usb_request      req;
+       struct list_head        queue;
+};
+
+struct m66592_ep {
+       struct usb_ep           ep;
+       struct m66592           *m66592;
+
+       struct list_head        queue;
+       unsigned                busy:1;
+       unsigned                internal_ccpl:1;        /* use only control */
+
+       /* this member can able to after m66592_enable */
+       unsigned                use_dma:1;
+       u16                     pipenum;
+       u16                     type;
+       const struct usb_endpoint_descriptor    *desc;
+       /* register address */
+       unsigned long           fifoaddr;
+       unsigned long           fifosel;
+       unsigned long           fifoctr;
+       unsigned long           fifotrn;
+       unsigned long           pipectr;
+};
+
+struct m66592 {
+       spinlock_t              lock;
+       void __iomem            *reg;
+
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+
+       struct m66592_ep        ep[M66592_MAX_NUM_PIPE];
+       struct m66592_ep        *pipenum2ep[M66592_MAX_NUM_PIPE];
+       struct m66592_ep        *epaddr2ep[16];
+
+       struct usb_request      *ep0_req;       /* for internal request */
+       u16                     *ep0_buf;       /* for internal request */
+
+       struct timer_list       timer;
+
+       u16                     old_vbus;
+       int                     scount;
+
+       int                     old_dvsq;
+
+       /* pipe config */
+       int bulk;
+       int interrupt;
+       int isochronous;
+       int num_dma;
+       int bi_bufnum;  /* bulk and isochronous's bufnum */
+};
+
+#define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
+#define m66592_to_gadget(m66592) (&m66592->gadget)
+
+#define is_bulk_pipe(pipenum)  \
+       ((pipenum >= M66592_BASE_PIPENUM_BULK) && \
+        (pipenum < (M66592_BASE_PIPENUM_BULK + M66592_MAX_NUM_BULK)))
+#define is_interrupt_pipe(pipenum)     \
+       ((pipenum >= M66592_BASE_PIPENUM_INT) && \
+        (pipenum < (M66592_BASE_PIPENUM_INT + M66592_MAX_NUM_INT)))
+#define is_isoc_pipe(pipenum)  \
+       ((pipenum >= M66592_BASE_PIPENUM_ISOC) && \
+        (pipenum < (M66592_BASE_PIPENUM_ISOC + M66592_MAX_NUM_ISOC)))
+
+#define enable_irq_ready(m66592, pipenum)      \
+       enable_pipe_irq(m66592, pipenum, M66592_BRDYENB)
+#define disable_irq_ready(m66592, pipenum)     \
+       disable_pipe_irq(m66592, pipenum, M66592_BRDYENB)
+#define enable_irq_empty(m66592, pipenum)      \
+       enable_pipe_irq(m66592, pipenum, M66592_BEMPENB)
+#define disable_irq_empty(m66592, pipenum)     \
+       disable_pipe_irq(m66592, pipenum, M66592_BEMPENB)
+#define enable_irq_nrdy(m66592, pipenum)       \
+       enable_pipe_irq(m66592, pipenum, M66592_NRDYENB)
+#define disable_irq_nrdy(m66592, pipenum)      \
+       disable_pipe_irq(m66592, pipenum, M66592_NRDYENB)
+
+/*-------------------------------------------------------------------------*/
+static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset)
+{
+       return inw((unsigned long)m66592->reg + offset);
+}
+
+static inline void m66592_read_fifo(struct m66592 *m66592,
+                                   unsigned long offset,
+                                   void *buf, unsigned long len)
+{
+       unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+
+       len = (len + 1) / 2;
+       insw(fifoaddr, buf, len);
+}
+
+static inline void m66592_write(struct m66592 *m66592, u16 val,
+                               unsigned long offset)
+{
+       outw(val, (unsigned long)m66592->reg + offset);
+}
+
+static inline void m66592_write_fifo(struct m66592 *m66592,
+                                    unsigned long offset,
+                                    void *buf, unsigned long len)
+{
+       unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+       unsigned long odd = len & 0x0001;
+
+       len = len / 2;
+       outsw(fifoaddr, buf, len);
+       if (odd) {
+               unsigned char *p = buf + len*2;
+               outb(*p, fifoaddr);
+       }
+}
+
+static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
+                              unsigned long offset)
+{
+       u16 tmp;
+       tmp = m66592_read(m66592, offset);
+       tmp = tmp & (~pat);
+       tmp = tmp | val;
+       m66592_write(m66592, tmp, offset);
+}
+
+#define m66592_bclr(m66592, val, offset)       \
+                       m66592_mdfy(m66592, 0, val, offset)
+#define m66592_bset(m66592, val, offset)       \
+                       m66592_mdfy(m66592, val, 0, offset)
+
+#endif /* ifndef __M66592_UDC_H__ */
+
+
index d975ecf18e00537bb6a67895f04f4a5bd00b6ee5..c3d364ecd4f8e48dbd6f3236bf2eb520f2906272 100644 (file)
@@ -450,100 +450,6 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req)
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * dma-coherent memory allocation (for dma-capable endpoints)
- *
- * NOTE: the dma_*_coherent() API calls suck.  Most implementations are
- * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
- * respect to calls with irqs disabled:  alloc is safe, free is not.
- * We currently work around (b), but not (a).
- */
-
-static void *
-net2280_alloc_buffer (
-       struct usb_ep           *_ep,
-       unsigned                bytes,
-       dma_addr_t              *dma,
-       gfp_t                   gfp_flags
-)
-{
-       void                    *retval;
-       struct net2280_ep       *ep;
-
-       ep = container_of (_ep, struct net2280_ep, ep);
-       if (!_ep)
-               return NULL;
-       *dma = DMA_ADDR_INVALID;
-
-       if (ep->dma)
-               retval = dma_alloc_coherent(&ep->dev->pdev->dev,
-                               bytes, dma, gfp_flags);
-       else
-               retval = kmalloc(bytes, gfp_flags);
-       return retval;
-}
-
-static DEFINE_SPINLOCK(buflock);
-static LIST_HEAD(buffers);
-
-struct free_record {
-       struct list_head        list;
-       struct device           *dev;
-       unsigned                bytes;
-       dma_addr_t              dma;
-};
-
-static void do_free(unsigned long ignored)
-{
-       spin_lock_irq(&buflock);
-       while (!list_empty(&buffers)) {
-               struct free_record      *buf;
-
-               buf = list_entry(buffers.next, struct free_record, list);
-               list_del(&buf->list);
-               spin_unlock_irq(&buflock);
-
-               dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
-
-               spin_lock_irq(&buflock);
-       }
-       spin_unlock_irq(&buflock);
-}
-
-static DECLARE_TASKLET(deferred_free, do_free, 0);
-
-static void
-net2280_free_buffer (
-       struct usb_ep *_ep,
-       void *address,
-       dma_addr_t dma,
-       unsigned bytes
-) {
-       /* free memory into the right allocator */
-       if (dma != DMA_ADDR_INVALID) {
-               struct net2280_ep       *ep;
-               struct free_record      *buf = address;
-               unsigned long           flags;
-
-               ep = container_of(_ep, struct net2280_ep, ep);
-               if (!_ep)
-                       return;
-
-               ep = container_of (_ep, struct net2280_ep, ep);
-               buf->dev = &ep->dev->pdev->dev;
-               buf->bytes = bytes;
-               buf->dma = dma;
-
-               spin_lock_irqsave(&buflock, flags);
-               list_add_tail(&buf->list, &buffers);
-               tasklet_schedule(&deferred_free);
-               spin_unlock_irqrestore(&buflock, flags);
-       } else
-               kfree (address);
-}
-
-/*-------------------------------------------------------------------------*/
-
 /* load a packet into the fifo we use for usb IN transfers.
  * works for all endpoints.
  *
@@ -1392,9 +1298,6 @@ static const struct usb_ep_ops net2280_ep_ops = {
        .alloc_request  = net2280_alloc_request,
        .free_request   = net2280_free_request,
 
-       .alloc_buffer   = net2280_alloc_buffer,
-       .free_buffer    = net2280_free_buffer,
-
        .queue          = net2280_queue,
        .dequeue        = net2280_dequeue,
 
@@ -2964,7 +2867,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
                        , &dev->pci->pcimstctl);
        /* erratum 0115 shouldn't appear: Linux inits PCI_LATENCY_TIMER */
        pci_set_master (pdev);
-       pci_set_mwi (pdev);
+       pci_try_set_mwi (pdev);
 
        /* ... also flushes any posted pci writes */
        dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff;
index c4975a6cf7774cc32fcd0ff3500462694b2c0f7b..9b0f0925dddf644259865cb9f54ac1a8a2c534cc 100644 (file)
@@ -296,111 +296,6 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req)
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * dma-coherent memory allocation (for dma-capable endpoints)
- *
- * NOTE: the dma_*_coherent() API calls suck.  Most implementations are
- * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
- * respect to calls with irqs disabled:  alloc is safe, free is not.
- * We currently work around (b), but not (a).
- */
-
-static void *
-omap_alloc_buffer(
-       struct usb_ep   *_ep,
-       unsigned        bytes,
-       dma_addr_t      *dma,
-       gfp_t           gfp_flags
-)
-{
-       void            *retval;
-       struct omap_ep  *ep;
-
-       if (!_ep)
-               return NULL;
-
-       ep = container_of(_ep, struct omap_ep, ep);
-       if (use_dma && ep->has_dma) {
-               static int      warned;
-               if (!warned && bytes < PAGE_SIZE) {
-                       dev_warn(ep->udc->gadget.dev.parent,
-                               "using dma_alloc_coherent for "
-                               "small allocations wastes memory\n");
-                       warned++;
-               }
-               return dma_alloc_coherent(ep->udc->gadget.dev.parent,
-                               bytes, dma, gfp_flags);
-       }
-
-       retval = kmalloc(bytes, gfp_flags);
-       if (retval)
-               *dma = virt_to_phys(retval);
-       return retval;
-}
-
-static DEFINE_SPINLOCK(buflock);
-static LIST_HEAD(buffers);
-
-struct free_record {
-       struct list_head        list;
-       struct device           *dev;
-       unsigned                bytes;
-       dma_addr_t              dma;
-};
-
-static void do_free(unsigned long ignored)
-{
-       spin_lock_irq(&buflock);
-       while (!list_empty(&buffers)) {
-               struct free_record      *buf;
-
-               buf = list_entry(buffers.next, struct free_record, list);
-               list_del(&buf->list);
-               spin_unlock_irq(&buflock);
-
-               dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
-
-               spin_lock_irq(&buflock);
-       }
-       spin_unlock_irq(&buflock);
-}
-
-static DECLARE_TASKLET(deferred_free, do_free, 0);
-
-static void omap_free_buffer(
-       struct usb_ep   *_ep,
-       void            *buf,
-       dma_addr_t      dma,
-       unsigned        bytes
-)
-{
-       if (!_ep) {
-               WARN_ON(1);
-               return;
-       }
-
-       /* free memory into the right allocator */
-       if (dma != DMA_ADDR_INVALID) {
-               struct omap_ep          *ep;
-               struct free_record      *rec = buf;
-               unsigned long           flags;
-
-               ep = container_of(_ep, struct omap_ep, ep);
-
-               rec->dev = ep->udc->gadget.dev.parent;
-               rec->bytes = bytes;
-               rec->dma = dma;
-
-               spin_lock_irqsave(&buflock, flags);
-               list_add_tail(&rec->list, &buffers);
-               tasklet_schedule(&deferred_free);
-               spin_unlock_irqrestore(&buflock, flags);
-       } else
-               kfree(buf);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static void
 done(struct omap_ep *ep, struct omap_req *req, int status)
 {
@@ -1271,9 +1166,6 @@ static struct usb_ep_ops omap_ep_ops = {
        .alloc_request  = omap_alloc_request,
        .free_request   = omap_free_request,
 
-       .alloc_buffer   = omap_alloc_buffer,
-       .free_buffer    = omap_free_buffer,
-
        .queue          = omap_ep_queue,
        .dequeue        = omap_ep_dequeue,
 
index 84392e835d5f12c598bec4823b9d3b352bd7b4ca..63b9521c1322018a4c494f32c0174cb190a11181 100644 (file)
@@ -24,9 +24,9 @@
  *
  */
 
-#undef DEBUG
 // #define     VERBOSE DBG_VERBOSE
 
+#include <linux/device.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 
 #include <asm/byteorder.h>
 #include <asm/dma.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
 #include <asm/unaligned.h>
 #include <asm/hardware.h>
-#ifdef CONFIG_ARCH_PXA
-#include <asm/arch/pxa-regs.h>
-#endif
 
 #include <linux/usb/ch9.h>
 #include <linux/usb_gadget.h>
 
-#include <asm/arch/udc.h>
+#include <asm/mach/udc_pxa2xx.h>
 
 
 /*
  * it constrains the sorts of USB configuration change events that work.
  * The errata for these chips are misleading; some "fixed" bugs from
  * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
+ *
+ * Note that the UDC hardware supports DMA (except on IXP) but that's
+ * not used here.  IN-DMA (to host) is simple enough, when the data is
+ * suitably aligned (16 bytes) ... the network stack doesn't do that,
+ * other software can.  OUT-DMA is buggy in most chip versions, as well
+ * as poorly designed (data toggle not automatic).  So this driver won't
+ * bother using DMA.  (Mostly-working IN-DMA support was available in
+ * kernels before 2.6.23, but was never enabled or well tested.)
  */
 
-#define        DRIVER_VERSION  "4-May-2005"
+#define        DRIVER_VERSION  "30-June-2007"
 #define        DRIVER_DESC     "PXA 25x USB Device Controller driver"
 
 
@@ -87,12 +93,9 @@ static const char driver_name [] = "pxa2xx_udc";
 static const char ep0name [] = "ep0";
 
 
-// #define     USE_DMA
-// #define     USE_OUT_DMA
 // #define     DISABLE_TEST_MODE
 
 #ifdef CONFIG_ARCH_IXP4XX
-#undef USE_DMA
 
 /* cpu-specific register addresses are compiled in to this code */
 #ifdef CONFIG_ARCH_PXA
@@ -104,25 +107,6 @@ static const char ep0name [] = "ep0";
 #include "pxa2xx_udc.h"
 
 
-#ifdef USE_DMA
-static int use_dma = 1;
-module_param(use_dma, bool, 0);
-MODULE_PARM_DESC (use_dma, "true to use dma");
-
-static void dma_nodesc_handler (int dmach, void *_ep);
-static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req);
-
-#ifdef USE_OUT_DMA
-#define        DMASTR " (dma support)"
-#else
-#define        DMASTR " (dma in)"
-#endif
-
-#else  /* !USE_DMA */
-#define        DMASTR " (pio only)"
-#undef USE_OUT_DMA
-#endif
-
 #ifdef CONFIG_USB_PXA2XX_SMALL
 #define SIZE_STR       " (small)"
 #else
@@ -155,7 +139,7 @@ static int is_vbus_present(void)
        struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
 
        if (mach->gpio_vbus)
-               return udc_gpio_get(mach->gpio_vbus);
+               return gpio_get_value(mach->gpio_vbus);
        if (mach->udc_is_connected)
                return mach->udc_is_connected();
        return 1;
@@ -167,7 +151,7 @@ static void pullup_off(void)
        struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
 
        if (mach->gpio_pullup)
-               udc_gpio_set(mach->gpio_pullup, 0);
+               gpio_set_value(mach->gpio_pullup, 0);
        else if (mach->udc_command)
                mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
 }
@@ -177,7 +161,7 @@ static void pullup_on(void)
        struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
 
        if (mach->gpio_pullup)
-               udc_gpio_set(mach->gpio_pullup, 1);
+               gpio_set_value(mach->gpio_pullup, 1);
        else if (mach->udc_command)
                mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
 }
@@ -281,9 +265,8 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
        }
 
        ep->desc = desc;
-       ep->dma = -1;
        ep->stopped = 0;
-       ep->pio_irqs = ep->dma_irqs = 0;
+       ep->pio_irqs = 0;
        ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize);
 
        /* flush fifo (mostly for OUT buffers) */
@@ -291,30 +274,6 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
 
        /* ... reset halt state too, if we could ... */
 
-#ifdef USE_DMA
-       /* for (some) bulk and ISO endpoints, try to get a DMA channel and
-        * bind it to the endpoint.  otherwise use PIO.
-        */
-       switch (ep->bmAttributes) {
-       case USB_ENDPOINT_XFER_ISOC:
-               if (le16_to_cpu(desc->wMaxPacketSize) % 32)
-                       break;
-               // fall through
-       case USB_ENDPOINT_XFER_BULK:
-               if (!use_dma || !ep->reg_drcmr)
-                       break;
-               ep->dma = pxa_request_dma ((char *)_ep->name,
-                               (le16_to_cpu (desc->wMaxPacketSize) > 64)
-                                       ? DMA_PRIO_MEDIUM /* some iso */
-                                       : DMA_PRIO_LOW,
-                               dma_nodesc_handler, ep);
-               if (ep->dma >= 0) {
-                       *ep->reg_drcmr = DRCMR_MAPVLD | ep->dma;
-                       DMSG("%s using dma%d\n", _ep->name, ep->dma);
-               }
-       }
-#endif
-
        DBG(DBG_VERBOSE, "enabled %s\n", _ep->name);
        return 0;
 }
@@ -334,14 +293,6 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
 
        nuke (ep, -ESHUTDOWN);
 
-#ifdef USE_DMA
-       if (ep->dma >= 0) {
-               *ep->reg_drcmr = 0;
-               pxa_free_dma (ep->dma);
-               ep->dma = -1;
-       }
-#endif
-
        /* flush fifo (mostly for IN buffers) */
        pxa2xx_ep_fifo_flush (_ep);
 
@@ -390,35 +341,6 @@ pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
        kfree(req);
 }
 
-
-/* PXA cache needs flushing with DMA I/O (it's dma-incoherent), but there's
- * no device-affinity and the heap works perfectly well for i/o buffers.
- * It wastes much less memory than dma_alloc_coherent() would, and even
- * prevents cacheline (32 bytes wide) sharing problems.
- */
-static void *
-pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-       dma_addr_t *dma, gfp_t gfp_flags)
-{
-       char                    *retval;
-
-       retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM));
-       if (retval)
-#ifdef USE_DMA
-               *dma = virt_to_bus (retval);
-#else
-               *dma = (dma_addr_t)~0;
-#endif
-       return retval;
-}
-
-static void
-pxa2xx_ep_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma,
-               unsigned bytes)
-{
-       kfree (buf);
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -518,18 +440,8 @@ write_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
                /* requests complete when all IN data is in the FIFO */
                if (is_last) {
                        done (ep, req, 0);
-                       if (list_empty(&ep->queue) || unlikely(ep->dma >= 0)) {
+                       if (list_empty(&ep->queue))
                                pio_irq_disable (ep->bEndpointAddress);
-#ifdef USE_DMA
-                               /* unaligned data and zlps couldn't use dma */
-                               if (unlikely(!list_empty(&ep->queue))) {
-                                       req = list_entry(ep->queue.next,
-                                               struct pxa2xx_request, queue);
-                                       kick_dma(ep,req);
-                                       return 0;
-                               }
-#endif
-                       }
                        return 1;
                }
 
@@ -728,182 +640,6 @@ read_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
        return 0;
 }
 
-#ifdef USE_DMA
-
-#define        MAX_IN_DMA      ((DCMD_LENGTH + 1) - BULK_FIFO_SIZE)
-
-static void
-start_dma_nodesc(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int is_in)
-{
-       u32     dcmd = req->req.length;
-       u32     buf = req->req.dma;
-       u32     fifo = io_v2p ((u32)ep->reg_uddr);
-
-       /* caller guarantees there's a packet or more remaining
-        *  - IN may end with a short packet (TSP set separately),
-        *  - OUT is always full length
-        */
-       buf += req->req.actual;
-       dcmd -= req->req.actual;
-       ep->dma_fixup = 0;
-
-       /* no-descriptor mode can be simple for bulk-in, iso-in, iso-out */
-       DCSR(ep->dma) = DCSR_NODESC;
-       if (is_in) {
-               DSADR(ep->dma) = buf;
-               DTADR(ep->dma) = fifo;
-               if (dcmd > MAX_IN_DMA)
-                       dcmd = MAX_IN_DMA;
-               else
-                       ep->dma_fixup = (dcmd % ep->ep.maxpacket) != 0;
-               dcmd |= DCMD_BURST32 | DCMD_WIDTH1
-                       | DCMD_FLOWTRG | DCMD_INCSRCADDR;
-       } else {
-#ifdef USE_OUT_DMA
-               DSADR(ep->dma) = fifo;
-               DTADR(ep->dma) = buf;
-               if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC)
-                       dcmd = ep->ep.maxpacket;
-               dcmd |= DCMD_BURST32 | DCMD_WIDTH1
-                       | DCMD_FLOWSRC | DCMD_INCTRGADDR;
-#endif
-       }
-       DCMD(ep->dma) = dcmd;
-       DCSR(ep->dma) = DCSR_RUN | DCSR_NODESC
-               | (unlikely(is_in)
-                       ? DCSR_STOPIRQEN        /* use dma_nodesc_handler() */
-                       : 0);                   /* use handle_ep() */
-}
-
-static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req)
-{
-       int     is_in = ep->bEndpointAddress & USB_DIR_IN;
-
-       if (is_in) {
-               /* unaligned tx buffers and zlps only work with PIO */
-               if ((req->req.dma & 0x0f) != 0
-                               || unlikely((req->req.length - req->req.actual)
-                                               == 0)) {
-                       pio_irq_enable(ep->bEndpointAddress);
-                       if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0)
-                               (void) write_fifo(ep, req);
-               } else {
-                       start_dma_nodesc(ep, req, USB_DIR_IN);
-               }
-       } else {
-               if ((req->req.length - req->req.actual) < ep->ep.maxpacket) {
-                       DMSG("%s short dma read...\n", ep->ep.name);
-                       /* we're always set up for pio out */
-                       read_fifo (ep, req);
-               } else {
-                       *ep->reg_udccs = UDCCS_BO_DME
-                               | (*ep->reg_udccs & UDCCS_BO_FST);
-                       start_dma_nodesc(ep, req, USB_DIR_OUT);
-               }
-       }
-}
-
-static void cancel_dma(struct pxa2xx_ep *ep)
-{
-       struct pxa2xx_request   *req;
-       u32                     tmp;
-
-       if (DCSR(ep->dma) == 0 || list_empty(&ep->queue))
-               return;
-
-       DCSR(ep->dma) = 0;
-       while ((DCSR(ep->dma) & DCSR_STOPSTATE) == 0)
-               cpu_relax();
-
-       req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
-       tmp = DCMD(ep->dma) & DCMD_LENGTH;
-       req->req.actual = req->req.length - (tmp & DCMD_LENGTH);
-
-       /* the last tx packet may be incomplete, so flush the fifo.
-        * FIXME correct req.actual if we can
-        */
-       if (ep->bEndpointAddress & USB_DIR_IN)
-               *ep->reg_udccs = UDCCS_BI_FTF;
-}
-
-/* dma channel stopped ... normal tx end (IN), or on error (IN/OUT) */
-static void dma_nodesc_handler(int dmach, void *_ep)
-{
-       struct pxa2xx_ep        *ep = _ep;
-       struct pxa2xx_request   *req;
-       u32                     tmp, completed;
-
-       local_irq_disable();
-
-       req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
-
-       ep->dma_irqs++;
-       ep->dev->stats.irqs++;
-       HEX_DISPLAY(ep->dev->stats.irqs);
-
-       /* ack/clear */
-       tmp = DCSR(ep->dma);
-       DCSR(ep->dma) = tmp;
-       if ((tmp & DCSR_STOPSTATE) == 0
-                       || (DDADR(ep->dma) & DDADR_STOP) != 0) {
-               DBG(DBG_VERBOSE, "%s, dcsr %08x ddadr %08x\n",
-                       ep->ep.name, DCSR(ep->dma), DDADR(ep->dma));
-               goto done;
-       }
-       DCSR(ep->dma) = 0;      /* clear DCSR_STOPSTATE */
-
-       /* update transfer status */
-       completed = tmp & DCSR_BUSERR;
-       if (ep->bEndpointAddress & USB_DIR_IN)
-               tmp = DSADR(ep->dma);
-       else
-               tmp = DTADR(ep->dma);
-       req->req.actual = tmp - req->req.dma;
-
-       /* FIXME seems we sometimes see partial transfers... */
-
-       if (unlikely(completed != 0))
-               req->req.status = -EIO;
-       else if (req->req.actual) {
-               /* these registers have zeroes in low bits; they miscount
-                * some (end-of-transfer) short packets:  tx 14 as tx 12
-                */
-               if (ep->dma_fixup)
-                       req->req.actual = min(req->req.actual + 3,
-                                               req->req.length);
-
-               tmp = (req->req.length - req->req.actual);
-               completed = (tmp == 0);
-               if (completed && (ep->bEndpointAddress & USB_DIR_IN)) {
-
-                       /* maybe validate final short packet ... */
-                       if ((req->req.actual % ep->ep.maxpacket) != 0)
-                               *ep->reg_udccs = UDCCS_BI_TSP/*|UDCCS_BI_TPC*/;
-
-                       /* ... or zlp, using pio fallback */
-                       else if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK
-                                       && req->req.zero) {
-                               DMSG("%s zlp terminate ...\n", ep->ep.name);
-                               completed = 0;
-                       }
-               }
-       }
-
-       if (likely(completed)) {
-               done(ep, req, 0);
-
-               /* maybe re-activate after completion */
-               if (ep->stopped || list_empty(&ep->queue))
-                       goto done;
-               req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
-       }
-       kick_dma(ep, req);
-done:
-       local_irq_enable();
-}
-
-#endif
-
 /*-------------------------------------------------------------------------*/
 
 static int
@@ -942,19 +678,8 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
                                                (ep->desc->wMaxPacketSize)))
                return -EMSGSIZE;
 
-#ifdef USE_DMA
-       // FIXME caller may already have done the dma mapping
-       if (ep->dma >= 0) {
-               _req->dma = dma_map_single(dev->dev,
-                       _req->buf, _req->length,
-                       ((ep->bEndpointAddress & USB_DIR_IN) != 0)
-                               ? DMA_TO_DEVICE
-                               : DMA_FROM_DEVICE);
-       }
-#endif
-
        DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
-            _ep->name, _req, _req->length, _req->buf);
+               _ep->name, _req, _req->length, _req->buf);
 
        local_irq_save(flags);
 
@@ -1002,11 +727,6 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
                                local_irq_restore (flags);
                                return -EL2HLT;
                        }
-#ifdef USE_DMA
-               /* either start dma or prime pio pump */
-               } else if (ep->dma >= 0) {
-                       kick_dma(ep, req);
-#endif
                /* can the FIFO can satisfy the request immediately? */
                } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
                        if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0
@@ -1017,7 +737,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
                        req = NULL;
                }
 
-               if (likely (req && ep->desc) && ep->dma < 0)
+               if (likely (req && ep->desc))
                        pio_irq_enable(ep->bEndpointAddress);
        }
 
@@ -1038,10 +758,6 @@ static void nuke(struct pxa2xx_ep *ep, int status)
        struct pxa2xx_request *req;
 
        /* called with irqs blocked */
-#ifdef USE_DMA
-       if (ep->dma >= 0 && !ep->stopped)
-               cancel_dma(ep);
-#endif
        while (!list_empty(&ep->queue)) {
                req = list_entry(ep->queue.next,
                                struct pxa2xx_request,
@@ -1076,19 +792,7 @@ static int pxa2xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
                return -EINVAL;
        }
 
-#ifdef USE_DMA
-       if (ep->dma >= 0 && ep->queue.next == &req->queue && !ep->stopped) {
-               cancel_dma(ep);
-               done(ep, req, -ECONNRESET);
-               /* restart i/o */
-               if (!list_empty(&ep->queue)) {
-                       req = list_entry(ep->queue.next,
-                                       struct pxa2xx_request, queue);
-                       kick_dma(ep, req);
-               }
-       } else
-#endif
-               done(ep, req, -ECONNRESET);
+       done(ep, req, -ECONNRESET);
 
        local_irq_restore(flags);
        return 0;
@@ -1203,9 +907,6 @@ static struct usb_ep_ops pxa2xx_ep_ops = {
        .alloc_request  = pxa2xx_ep_alloc_request,
        .free_request   = pxa2xx_ep_free_request,
 
-       .alloc_buffer   = pxa2xx_ep_alloc_buffer,
-       .free_buffer    = pxa2xx_ep_free_buffer,
-
        .queue          = pxa2xx_ep_queue,
        .dequeue        = pxa2xx_ep_dequeue,
 
@@ -1325,7 +1026,7 @@ udc_proc_read(char *page, char **start, off_t off, int count,
        /* basic device status */
        t = scnprintf(next, size, DRIVER_DESC "\n"
                "%s version: %s\nGadget driver: %s\nHost %s\n\n",
-               driver_name, DRIVER_VERSION SIZE_STR DMASTR,
+               driver_name, DRIVER_VERSION SIZE_STR "(pio)",
                dev->driver ? dev->driver->driver.name : "(none)",
                is_vbus_present() ? "full speed" : "disconnected");
        size -= t;
@@ -1390,7 +1091,6 @@ udc_proc_read(char *page, char **start, off_t off, int count,
        for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
                struct pxa2xx_ep        *ep = &dev->ep [i];
                struct pxa2xx_request   *req;
-               int                     t;
 
                if (i != 0) {
                        const struct usb_endpoint_descriptor    *d;
@@ -1400,10 +1100,9 @@ udc_proc_read(char *page, char **start, off_t off, int count,
                                continue;
                        tmp = *dev->ep [i].reg_udccs;
                        t = scnprintf(next, size,
-                               "%s max %d %s udccs %02x irqs %lu/%lu\n",
+                               "%s max %d %s udccs %02x irqs %lu\n",
                                ep->ep.name, le16_to_cpu (d->wMaxPacketSize),
-                               (ep->dma >= 0) ? "dma" : "pio", tmp,
-                               ep->pio_irqs, ep->dma_irqs);
+                               "pio", tmp, ep->pio_irqs);
                        /* TODO translate all five groups of udccs bits! */
 
                } else /* ep0 should only have one transfer queued */
@@ -1423,19 +1122,7 @@ udc_proc_read(char *page, char **start, off_t off, int count,
                        continue;
                }
                list_for_each_entry(req, &ep->queue, queue) {
-#ifdef USE_DMA
-                       if (ep->dma >= 0 && req->queue.prev == &ep->queue)
-                               t = scnprintf(next, size,
-                                       "\treq %p len %d/%d "
-                                       "buf %p (dma%d dcmd %08x)\n",
-                                       &req->req, req->req.actual,
-                                       req->req.length, req->req.buf,
-                                       ep->dma, DCMD(ep->dma)
-                                       // low 13 bits == bytes-to-go
-                                       );
-                       else
-#endif
-                               t = scnprintf(next, size,
+                       t = scnprintf(next, size,
                                        "\treq %p len %d/%d buf %p\n",
                                        &req->req, req->req.actual,
                                        req->req.length, req->req.buf);
@@ -1488,7 +1175,6 @@ static void udc_disable(struct pxa2xx_udc *dev)
 
        ep0_idle (dev);
        dev->gadget.speed = USB_SPEED_UNKNOWN;
-       LED_CONNECTED_OFF;
 }
 
 
@@ -1514,7 +1200,7 @@ static void udc_reinit(struct pxa2xx_udc *dev)
                ep->desc = NULL;
                ep->stopped = 0;
                INIT_LIST_HEAD (&ep->queue);
-               ep->pio_irqs = ep->dma_irqs = 0;
+               ep->pio_irqs = 0;
        }
 
        /* the rest was statically initialized, and is read-only */
@@ -1666,7 +1352,6 @@ stop_activity(struct pxa2xx_udc *dev, struct usb_gadget_driver *driver)
        del_timer_sync(&dev->timer);
 
        /* report disconnect; the driver is already quiesced */
-       LED_CONNECTED_OFF;
        if (driver)
                driver->disconnect(&dev->gadget);
 
@@ -1715,16 +1400,13 @@ lubbock_vbus_irq(int irq, void *_dev)
        int                     vbus;
 
        dev->stats.irqs++;
-       HEX_DISPLAY(dev->stats.irqs);
        switch (irq) {
        case LUBBOCK_USB_IRQ:
-               LED_CONNECTED_ON;
                vbus = 1;
                disable_irq(LUBBOCK_USB_IRQ);
                enable_irq(LUBBOCK_USB_DISC_IRQ);
                break;
        case LUBBOCK_USB_DISC_IRQ:
-               LED_CONNECTED_OFF;
                vbus = 0;
                disable_irq(LUBBOCK_USB_DISC_IRQ);
                enable_irq(LUBBOCK_USB_IRQ);
@@ -1742,7 +1424,7 @@ lubbock_vbus_irq(int irq, void *_dev)
 static irqreturn_t udc_vbus_irq(int irq, void *_dev)
 {
        struct pxa2xx_udc       *dev = _dev;
-       int                     vbus = udc_gpio_get(dev->mach->gpio_vbus);
+       int                     vbus = gpio_get_value(dev->mach->gpio_vbus);
 
        pxa2xx_udc_vbus_session(&dev->gadget, vbus);
        return IRQ_HANDLED;
@@ -2040,18 +1722,6 @@ static void handle_ep(struct pxa2xx_ep *ep)
 
                        /* fifos can hold packets, ready for reading... */
                        if (likely(req)) {
-#ifdef USE_OUT_DMA
-// TODO didn't yet debug out-dma.  this approach assumes
-// the worst about short packets and RPC; it might be better.
-
-                               if (likely(ep->dma >= 0)) {
-                                       if (!(udccs & UDCCS_BO_RSP)) {
-                                               *ep->reg_udccs = UDCCS_BO_RPC;
-                                               ep->dma_irqs++;
-                                               return;
-                                       }
-                               }
-#endif
                                completed = read_fifo(ep, req);
                        } else
                                pio_irq_disable (ep->bEndpointAddress);
@@ -2074,7 +1744,6 @@ pxa2xx_udc_irq(int irq, void *_dev)
        int                     handled;
 
        dev->stats.irqs++;
-       HEX_DISPLAY(dev->stats.irqs);
        do {
                u32             udccr = UDCCR;
 
@@ -2125,7 +1794,6 @@ pxa2xx_udc_irq(int irq, void *_dev)
                        } else {
                                DBG(DBG_VERBOSE, "USB reset end\n");
                                dev->gadget.speed = USB_SPEED_FULL;
-                               LED_CONNECTED_ON;
                                memset(&dev->stats, 0, sizeof dev->stats);
                                /* driver and endpoints are still reset */
                        }
@@ -2217,7 +1885,6 @@ static struct pxa2xx_udc memory = {
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS1,
                .reg_uddr       = &UDDR1,
-               drcmr (25)
        },
        .ep[2] = {
                .ep = {
@@ -2232,7 +1899,6 @@ static struct pxa2xx_udc memory = {
                .reg_udccs      = &UDCCS2,
                .reg_ubcr       = &UBCR2,
                .reg_uddr       = &UDDR2,
-               drcmr (26)
        },
 #ifndef CONFIG_USB_PXA2XX_SMALL
        .ep[3] = {
@@ -2247,7 +1913,6 @@ static struct pxa2xx_udc memory = {
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS3,
                .reg_uddr       = &UDDR3,
-               drcmr (27)
        },
        .ep[4] = {
                .ep = {
@@ -2262,7 +1927,6 @@ static struct pxa2xx_udc memory = {
                .reg_udccs      = &UDCCS4,
                .reg_ubcr       = &UBCR4,
                .reg_uddr       = &UDDR4,
-               drcmr (28)
        },
        .ep[5] = {
                .ep = {
@@ -2291,7 +1955,6 @@ static struct pxa2xx_udc memory = {
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS6,
                .reg_uddr       = &UDDR6,
-               drcmr (30)
        },
        .ep[7] = {
                .ep = {
@@ -2306,7 +1969,6 @@ static struct pxa2xx_udc memory = {
                .reg_udccs      = &UDCCS7,
                .reg_ubcr       = &UBCR7,
                .reg_uddr       = &UDDR7,
-               drcmr (31)
        },
        .ep[8] = {
                .ep = {
@@ -2320,7 +1982,6 @@ static struct pxa2xx_udc memory = {
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS8,
                .reg_uddr       = &UDDR8,
-               drcmr (32)
        },
        .ep[9] = {
                .ep = {
@@ -2335,7 +1996,6 @@ static struct pxa2xx_udc memory = {
                .reg_udccs      = &UDCCS9,
                .reg_ubcr       = &UBCR9,
                .reg_uddr       = &UDDR9,
-               drcmr (33)
        },
        .ep[10] = {
                .ep = {
@@ -2364,7 +2024,6 @@ static struct pxa2xx_udc memory = {
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS11,
                .reg_uddr       = &UDDR11,
-               drcmr (35)
        },
        .ep[12] = {
                .ep = {
@@ -2379,7 +2038,6 @@ static struct pxa2xx_udc memory = {
                .reg_udccs      = &UDCCS12,
                .reg_ubcr       = &UBCR12,
                .reg_uddr       = &UDDR12,
-               drcmr (36)
        },
        .ep[13] = {
                .ep = {
@@ -2393,7 +2051,6 @@ static struct pxa2xx_udc memory = {
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS13,
                .reg_uddr       = &UDDR13,
-               drcmr (37)
        },
        .ep[14] = {
                .ep = {
@@ -2408,7 +2065,6 @@ static struct pxa2xx_udc memory = {
                .reg_udccs      = &UDCCS14,
                .reg_ubcr       = &UBCR14,
                .reg_uddr       = &UDDR14,
-               drcmr (38)
        },
        .ep[15] = {
                .ep = {
@@ -2466,7 +2122,7 @@ static struct pxa2xx_udc memory = {
 static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 {
        struct pxa2xx_udc *dev = &memory;
-       int retval, out_dma = 1, vbus_irq, irq;
+       int retval, vbus_irq, irq;
        u32 chiprev;
 
        /* insist on Intel/ARM/XScale */
@@ -2489,7 +2145,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
        case PXA250_B2: case PXA210_B2:
        case PXA250_B1: case PXA210_B1:
        case PXA250_B0: case PXA210_B0:
-               out_dma = 0;
+               /* OUT-DMA is broken ... */
                /* fall through */
        case PXA250_C0: case PXA210_C0:
                break;
@@ -2498,11 +2154,9 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
        case IXP425_B0:
        case IXP465_AD:
                dev->has_cfr = 1;
-               out_dma = 0;
                break;
 #endif
        default:
-               out_dma = 0;
                printk(KERN_ERR "%s: unrecognized processor: %08x\n",
                        driver_name, chiprev);
                /* iop3xx, ixp4xx, ... */
@@ -2513,36 +2167,41 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
        if (irq < 0)
                return -ENODEV;
 
-       pr_debug("%s: IRQ %d%s%s%s\n", driver_name, irq,
+       pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
                dev->has_cfr ? "" : " (!cfr)",
-               out_dma ? "" : " (broken dma-out)",
-               SIZE_STR DMASTR
+               SIZE_STR "(pio)"
                );
 
-#ifdef USE_DMA
-#ifndef        USE_OUT_DMA
-       out_dma = 0;
-#endif
-       /* pxa 250 erratum 130 prevents using OUT dma (fixed C0) */
-       if (!out_dma) {
-               DMSG("disabled OUT dma\n");
-               dev->ep[ 2].reg_drcmr = dev->ep[ 4].reg_drcmr = 0;
-               dev->ep[ 7].reg_drcmr = dev->ep[ 9].reg_drcmr = 0;
-               dev->ep[12].reg_drcmr = dev->ep[14].reg_drcmr = 0;
-       }
-#endif
-
        /* other non-static parts of init */
        dev->dev = &pdev->dev;
        dev->mach = pdev->dev.platform_data;
+
        if (dev->mach->gpio_vbus) {
-               udc_gpio_init_vbus(dev->mach->gpio_vbus);
-               vbus_irq = udc_gpio_to_irq(dev->mach->gpio_vbus);
+               if ((retval = gpio_request(dev->mach->gpio_vbus,
+                               "pxa2xx_udc GPIO VBUS"))) {
+                       dev_dbg(&pdev->dev,
+                               "can't get vbus gpio %d, err: %d\n",
+                               dev->mach->gpio_vbus, retval);
+                       return -EBUSY;
+               }
+               gpio_direction_input(dev->mach->gpio_vbus);
+               vbus_irq = gpio_to_irq(dev->mach->gpio_vbus);
                set_irq_type(vbus_irq, IRQT_BOTHEDGE);
        } else
                vbus_irq = 0;
-       if (dev->mach->gpio_pullup)
-               udc_gpio_init_pullup(dev->mach->gpio_pullup);
+
+       if (dev->mach->gpio_pullup) {
+               if ((retval = gpio_request(dev->mach->gpio_pullup,
+                               "pca2xx_udc GPIO PULLUP"))) {
+                       dev_dbg(&pdev->dev,
+                               "can't get pullup gpio %d, err: %d\n",
+                               dev->mach->gpio_pullup, retval);
+                       if (dev->mach->gpio_vbus)
+                               gpio_free(dev->mach->gpio_vbus);
+                       return -EBUSY;
+               }
+               gpio_direction_output(dev->mach->gpio_pullup, 0);
+       }
 
        init_timer(&dev->timer);
        dev->timer.function = udc_watchdog;
@@ -2566,6 +2225,10 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
        if (retval != 0) {
                printk(KERN_ERR "%s: can't get irq %d, err %d\n",
                        driver_name, irq, retval);
+               if (dev->mach->gpio_pullup)
+                       gpio_free(dev->mach->gpio_pullup);
+               if (dev->mach->gpio_vbus)
+                       gpio_free(dev->mach->gpio_vbus);
                return -EBUSY;
        }
        dev->got_irq = 1;
@@ -2581,6 +2244,10 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
                                driver_name, LUBBOCK_USB_DISC_IRQ, retval);
 lubbock_fail0:
                        free_irq(irq, dev);
+                       if (dev->mach->gpio_pullup)
+                               gpio_free(dev->mach->gpio_pullup);
+                       if (dev->mach->gpio_vbus)
+                               gpio_free(dev->mach->gpio_vbus);
                        return -EBUSY;
                }
                retval = request_irq(LUBBOCK_USB_IRQ,
@@ -2593,11 +2260,6 @@ lubbock_fail0:
                        free_irq(LUBBOCK_USB_DISC_IRQ, dev);
                        goto lubbock_fail0;
                }
-#ifdef DEBUG
-               /* with U-Boot (but not BLOB), hex is off by default */
-               HEX_DISPLAY(dev->stats.irqs);
-               LUB_DISC_BLNK_LED &= 0xff;
-#endif
        } else
 #endif
        if (vbus_irq) {
@@ -2608,6 +2270,10 @@ lubbock_fail0:
                        printk(KERN_ERR "%s: can't get irq %i, err %d\n",
                                driver_name, vbus_irq, retval);
                        free_irq(irq, dev);
+                       if (dev->mach->gpio_pullup)
+                               gpio_free(dev->mach->gpio_pullup);
+                       if (dev->mach->gpio_vbus)
+                               gpio_free(dev->mach->gpio_vbus);
                        return -EBUSY;
                }
        }
@@ -2641,8 +2307,13 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
                free_irq(LUBBOCK_USB_IRQ, dev);
        }
 #endif
-       if (dev->mach->gpio_vbus)
-               free_irq(IRQ_GPIO(dev->mach->gpio_vbus), dev);
+       if (dev->mach->gpio_vbus) {
+               free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev);
+               gpio_free(dev->mach->gpio_vbus);
+       }
+       if (dev->mach->gpio_pullup)
+               gpio_free(dev->mach->gpio_pullup);
+
        platform_set_drvdata(pdev, NULL);
        the_controller = NULL;
        return 0;
index 773e549aff3f721eb1f7b0ace82b45ff51b4c470..0e5d0e6fb0e2a26eb49e8bcc48a809fca81fbe23 100644 (file)
@@ -54,8 +54,6 @@ struct pxa2xx_ep {
        const struct usb_endpoint_descriptor    *desc;
        struct list_head                        queue;
        unsigned long                           pio_irqs;
-       unsigned long                           dma_irqs;
-       short                                   dma; 
 
        unsigned short                          fifo_size;
        u8                                      bEndpointAddress;
@@ -63,7 +61,7 @@ struct pxa2xx_ep {
 
        unsigned                                stopped : 1;
        unsigned                                dma_fixup : 1;
-                                                        
+
        /* UDCCS = UDC Control/Status for this EP
         * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
         * UDDR = UDC Endpoint Data Register (the fifo)
@@ -72,12 +70,6 @@ struct pxa2xx_ep {
        volatile u32                            *reg_udccs;
        volatile u32                            *reg_ubcr;
        volatile u32                            *reg_uddr;
-#ifdef USE_DMA
-       volatile u32                    *reg_drcmr;
-#define        drcmr(n)  .reg_drcmr = & DRCMR ## n ,
-#else
-#define        drcmr(n)  
-#endif
 };
 
 struct pxa2xx_request {
@@ -85,7 +77,7 @@ struct pxa2xx_request {
        struct list_head                        queue;
 };
 
-enum ep0_state { 
+enum ep0_state {
        EP0_IDLE,
        EP0_IN_DATA_PHASE,
        EP0_OUT_DATA_PHASE,
@@ -108,7 +100,6 @@ struct udc_stats {
 
 #ifdef CONFIG_USB_PXA2XX_SMALL
 /* when memory's tight, SMALL config saves code+data.  */
-#undef USE_DMA
 #define        PXA_UDC_NUM_ENDPOINTS   3
 #endif
 
@@ -144,37 +135,8 @@ struct pxa2xx_udc {
 #ifdef CONFIG_ARCH_LUBBOCK
 #include <asm/arch/lubbock.h>
 /* lubbock can also report usb connect/disconnect irqs */
-
-#ifdef DEBUG
-#define HEX_DISPLAY(n) if (machine_is_lubbock()) { LUB_HEXLED = (n); }
 #endif
 
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/* LEDs are only for debug */
-#ifndef HEX_DISPLAY
-#define HEX_DISPLAY(n)         do {} while(0)
-#endif
-
-#ifdef DEBUG
-#include <asm/leds.h>
-
-#define LED_CONNECTED_ON       leds_event(led_green_on)
-#define LED_CONNECTED_OFF      do { \
-                                       leds_event(led_green_off); \
-                                       HEX_DISPLAY(0); \
-                               } while(0)
-#endif
-
-#ifndef LED_CONNECTED_ON
-#define LED_CONNECTED_ON       do {} while(0)
-#define LED_CONNECTED_OFF      do {} while(0)
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 static struct pxa2xx_udc *the_controller;
 
 /*-------------------------------------------------------------------------*/
@@ -204,7 +166,7 @@ static const char *state_name[] = {
 #    define UDC_DEBUG DBG_NORMAL
 #endif
 
-static void __attribute__ ((__unused__))
+static void __maybe_unused
 dump_udccr(const char *label)
 {
        u32     udccr = UDCCR;
@@ -220,7 +182,7 @@ dump_udccr(const char *label)
                (udccr & UDCCR_UDE) ? " ude" : "");
 }
 
-static void __attribute__ ((__unused__))
+static void __maybe_unused
 dump_udccs0(const char *label)
 {
        u32             udccs0 = UDCCS0;
@@ -237,7 +199,7 @@ dump_udccs0(const char *label)
                (udccs0 & UDCCS0_OPR) ? " opr" : "");
 }
 
-static void __attribute__ ((__unused__))
+static void __maybe_unused
 dump_state(struct pxa2xx_udc *dev)
 {
        u32             tmp;
index 708657c89132068f2bfdbb8cc7f3552cbc182cbe..db1b2bfcee4e65eb91cc0c9070f55cea556a76bc 100644 (file)
@@ -53,7 +53,7 @@
  */
 
 #if 0
-#define DEBUG(str,args...) do { \
+#define DBG(str,args...) do { \
        if (rndis_debug) \
                printk(KERN_DEBUG str , ## args ); \
        } while (0)
@@ -65,7 +65,7 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging");
 #else
 
 #define rndis_debug            0
-#define DEBUG(str,args...)     do{}while(0)
+#define DBG(str,args...)       do{}while(0)
 #endif
 
 #define RNDIS_MAX_CONFIGS      1
@@ -183,9 +183,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        if (!resp) return -ENOMEM;
 
        if (buf_len && rndis_debug > 1) {
-               DEBUG("query OID %08x value, len %d:\n", OID, buf_len);
+               DBG("query OID %08x value, len %d:\n", OID, buf_len);
                for (i = 0; i < buf_len; i += 16) {
-                       DEBUG ("%03d: %08x %08x %08x %08x\n", i,
+                       DBG("%03d: %08x %08x %08x %08x\n", i,
                                le32_to_cpu(get_unaligned((__le32 *)
                                        &buf[i])),
                                le32_to_cpu(get_unaligned((__le32 *)
@@ -207,7 +207,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_SUPPORTED_LIST:
-               DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
+               DBG("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
                length = sizeof (oid_supported_list);
                count  = length / sizeof (u32);
                for (i = 0; i < count; i++)
@@ -217,7 +217,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_HARDWARE_STATUS:
-               DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
+               DBG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
                /* Bogus question!
                 * Hardware must be ready to receive high level protocols.
                 * BTW:
@@ -230,14 +230,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_MEDIA_SUPPORTED:
-               DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
                *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
                retval = 0;
                break;
 
        /* mandatory */
        case OID_GEN_MEDIA_IN_USE:
-               DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
                /* one medium, one transport... (maybe you do it better) */
                *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
                retval = 0;
@@ -245,7 +245,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_MAXIMUM_FRAME_SIZE:
-               DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].dev) {
                        *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
@@ -256,7 +256,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_LINK_SPEED:
                if (rndis_debug > 1)
-                       DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].media_state
                                == NDIS_MEDIA_STATE_DISCONNECTED)
                        *outbuf = __constant_cpu_to_le32 (0);
@@ -268,7 +268,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_TRANSMIT_BLOCK_SIZE:
-               DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
+               DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].dev) {
                        *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
@@ -278,7 +278,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_RECEIVE_BLOCK_SIZE:
-               DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
+               DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].dev) {
                        *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
@@ -288,7 +288,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_VENDOR_ID:
-               DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
+               DBG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
                *outbuf = cpu_to_le32 (
                        rndis_per_dev_params [configNr].vendorID);
                retval = 0;
@@ -296,7 +296,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_VENDOR_DESCRIPTION:
-               DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
+               DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
                length = strlen (rndis_per_dev_params [configNr].vendorDescr);
                memcpy (outbuf,
                        rndis_per_dev_params [configNr].vendorDescr, length);
@@ -304,7 +304,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_VENDOR_DRIVER_VERSION:
-               DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
+               DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
                /* Created as LE */
                *outbuf = rndis_driver_version;
                retval = 0;
@@ -312,14 +312,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_CURRENT_PACKET_FILTER:
-               DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
+               DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
                *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
                retval = 0;
                break;
 
        /* mandatory */
        case OID_GEN_MAXIMUM_TOTAL_SIZE:
-               DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
                *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
                retval = 0;
                break;
@@ -327,14 +327,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_MEDIA_CONNECT_STATUS:
                if (rndis_debug > 1)
-                       DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
                *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                                .media_state);
                retval = 0;
                break;
 
        case OID_GEN_PHYSICAL_MEDIUM:
-               DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
+               DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
@@ -344,7 +344,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
         * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
         */
        case OID_GEN_MAC_OPTIONS:               /* from WinME */
-               DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
                *outbuf = __constant_cpu_to_le32(
                          NDIS_MAC_OPTION_RECEIVE_SERIALIZED
                        | NDIS_MAC_OPTION_FULL_DUPLEX);
@@ -356,7 +356,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_XMIT_OK:
                if (rndis_debug > 1)
-                       DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (
                            rndis_per_dev_params [configNr].stats->tx_packets -
@@ -369,7 +369,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_RCV_OK:
                if (rndis_debug > 1)
-                       DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (
                            rndis_per_dev_params [configNr].stats->rx_packets -
@@ -382,7 +382,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_XMIT_ERROR:
                if (rndis_debug > 1)
-                       DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->tx_errors);
@@ -393,7 +393,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_RCV_ERROR:
                if (rndis_debug > 1)
-                       DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_errors);
@@ -403,7 +403,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_RCV_NO_BUFFER:
-               DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
+               DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_dropped);
@@ -413,7 +413,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 #ifdef RNDIS_OPTIONAL_STATS
        case OID_GEN_DIRECTED_BYTES_XMIT:
-               DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
                /*
                 * Aunt Tilly's size of shoes
                 * minus antarctica count of penguins
@@ -433,7 +433,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_DIRECTED_FRAMES_XMIT:
-               DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
                /* dito */
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (
@@ -449,7 +449,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_MULTICAST_BYTES_XMIT:
-               DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast*1234);
@@ -458,7 +458,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_MULTICAST_FRAMES_XMIT:
-               DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast);
@@ -467,7 +467,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_BROADCAST_BYTES_XMIT:
-               DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->tx_packets/42*255);
@@ -476,7 +476,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_BROADCAST_FRAMES_XMIT:
-               DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->tx_packets/42);
@@ -485,19 +485,19 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_DIRECTED_BYTES_RCV:
-               DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
 
        case OID_GEN_DIRECTED_FRAMES_RCV:
-               DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
 
        case OID_GEN_MULTICAST_BYTES_RCV:
-               DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast * 1111);
@@ -506,7 +506,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_MULTICAST_FRAMES_RCV:
-               DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast);
@@ -515,7 +515,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_BROADCAST_BYTES_RCV:
-               DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_packets/42*255);
@@ -524,7 +524,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_BROADCAST_FRAMES_RCV:
-               DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_packets/42);
@@ -533,7 +533,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_RCV_CRC_ERROR:
-               DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
+               DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_crc_errors);
@@ -542,7 +542,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-               DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
+               DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
@@ -552,7 +552,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_PERMANENT_ADDRESS:
-               DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].dev) {
                        length = ETH_ALEN;
                        memcpy (outbuf,
@@ -564,7 +564,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_CURRENT_ADDRESS:
-               DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].dev) {
                        length = ETH_ALEN;
                        memcpy (outbuf,
@@ -576,7 +576,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_MULTICAST_LIST:
-               DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+               DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
                /* Multicast base address only */
                *outbuf = __constant_cpu_to_le32 (0xE0000000);
                retval = 0;
@@ -584,21 +584,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_MAXIMUM_LIST_SIZE:
-               DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
+               DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
                /* Multicast base address only */
                *outbuf = __constant_cpu_to_le32 (1);
                retval = 0;
                break;
 
        case OID_802_3_MAC_OPTIONS:
-               DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
                break;
 
        /* ieee802.3 statistics OIDs (table 4-4) */
 
        /* mandatory */
        case OID_802_3_RCV_ERROR_ALIGNMENT:
-               DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
+               DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_frame_errors);
@@ -608,51 +608,51 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_XMIT_ONE_COLLISION:
-               DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
 
        /* mandatory */
        case OID_802_3_XMIT_MORE_COLLISIONS:
-               DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
 
 #ifdef RNDIS_OPTIONAL_STATS
        case OID_802_3_XMIT_DEFERRED:
-               DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
                /* TODO */
                break;
 
        case OID_802_3_XMIT_MAX_COLLISIONS:
-               DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
                /* TODO */
                break;
 
        case OID_802_3_RCV_OVERRUN:
-               DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
+               DBG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
                /* TODO */
                break;
 
        case OID_802_3_XMIT_UNDERRUN:
-               DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
                /* TODO */
                break;
 
        case OID_802_3_XMIT_HEARTBEAT_FAILURE:
-               DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
                /* TODO */
                break;
 
        case OID_802_3_XMIT_TIMES_CRS_LOST:
-               DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
                /* TODO */
                break;
 
        case OID_802_3_XMIT_LATE_COLLISIONS:
-               DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
                /* TODO */
                break;
 #endif /* RNDIS_OPTIONAL_STATS */
@@ -660,7 +660,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 #ifdef RNDIS_PM
        /* power management OIDs (table 4-5) */
        case OID_PNP_CAPABILITIES:
-               DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
+               DBG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
 
                /* for now, no wakeup capabilities */
                length = sizeof (struct NDIS_PNP_CAPABILITIES);
@@ -668,7 +668,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                retval = 0;
                break;
        case OID_PNP_QUERY_POWER:
-               DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
+               DBG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
                                le32_to_cpu(get_unaligned((__le32 *)buf)) - 1);
                /* only suspend is a real power state, and
                 * it can't be entered by OID_PNP_SET_POWER...
@@ -705,9 +705,9 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
                return -ENOMEM;
 
        if (buf_len && rndis_debug > 1) {
-               DEBUG("set OID %08x value, len %d:\n", OID, buf_len);
+               DBG("set OID %08x value, len %d:\n", OID, buf_len);
                for (i = 0; i < buf_len; i += 16) {
-                       DEBUG ("%03d: %08x %08x %08x %08x\n", i,
+                       DBG("%03d: %08x %08x %08x %08x\n", i,
                                le32_to_cpu(get_unaligned((__le32 *)
                                        &buf[i])),
                                le32_to_cpu(get_unaligned((__le32 *)
@@ -731,7 +731,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
                 */
                *params->filter = (u16) le32_to_cpu(get_unaligned(
                                (__le32 *)buf));
-               DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+               DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
                        __FUNCTION__, *params->filter);
 
                /* this call has a significant side effect:  it's
@@ -756,7 +756,7 @@ update_linkstate:
 
        case OID_802_3_MULTICAST_LIST:
                /* I think we can ignore this */
-               DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+               DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
                retval = 0;
                break;
 #if 0
@@ -764,7 +764,7 @@ update_linkstate:
                {
                struct rndis_config_parameter   *param;
                param = (struct rndis_config_parameter *) buf;
-               DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
+               DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
                        __FUNCTION__,
                        min(cpu_to_le32(param->ParameterNameLength),80),
                        buf + param->ParameterNameOffset);
@@ -781,7 +781,7 @@ update_linkstate:
                 * FIXME ... then things go batty; Windows wedges itself.
                 */
                i = le32_to_cpu(get_unaligned((__le32 *)buf));
-               DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
+               DBG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
                switch (i) {
                case NdisDeviceStateD0:
                        *params->filter = params->saved_filter;
@@ -858,7 +858,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
        rndis_query_cmplt_type *resp;
        rndis_resp_t            *r;
 
-       // DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
+       // DBG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
        if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
 
        /*
@@ -911,15 +911,15 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
        BufOffset = le32_to_cpu (buf->InformationBufferOffset);
 
 #ifdef VERBOSE
-       DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
-       DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
-       DEBUG("%s: InfoBuffer: ", __FUNCTION__);
+       DBG("%s: Length: %d\n", __FUNCTION__, BufLength);
+       DBG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
+       DBG("%s: InfoBuffer: ", __FUNCTION__);
 
        for (i = 0; i < BufLength; i++) {
-               DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
+               DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
        }
 
-       DEBUG ("\n");
+       DBG("\n");
 #endif
 
        resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
@@ -1082,14 +1082,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
        /* For USB: responses may take up to 10 seconds */
        switch (MsgType) {
        case REMOTE_NDIS_INITIALIZE_MSG:
-               DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
+               DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
                        __FUNCTION__ );
                params->state = RNDIS_INITIALIZED;
                return  rndis_init_response (configNr,
                                        (rndis_init_msg_type *) buf);
 
        case REMOTE_NDIS_HALT_MSG:
-               DEBUG("%s: REMOTE_NDIS_HALT_MSG\n",
+               DBG("%s: REMOTE_NDIS_HALT_MSG\n",
                        __FUNCTION__ );
                params->state = RNDIS_UNINITIALIZED;
                if (params->dev) {
@@ -1107,7 +1107,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
                                        (rndis_set_msg_type *) buf);
 
        case REMOTE_NDIS_RESET_MSG:
-               DEBUG("%s: REMOTE_NDIS_RESET_MSG\n",
+               DBG("%s: REMOTE_NDIS_RESET_MSG\n",
                        __FUNCTION__ );
                return rndis_reset_response (configNr,
                                        (rndis_reset_msg_type *) buf);
@@ -1115,7 +1115,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
        case REMOTE_NDIS_KEEPALIVE_MSG:
                /* For USB: host does this every 5 seconds */
                if (rndis_debug > 1)
-                       DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
+                       DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
                                __FUNCTION__ );
                return rndis_keepalive_response (configNr,
                                                 (rndis_keepalive_msg_type *)
@@ -1132,7 +1132,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
                {
                        unsigned i;
                        for (i = 0; i < MsgLength; i += 16) {
-                               DEBUG ("%03d: "
+                               DBG("%03d: "
                                        " %02x %02x %02x %02x"
                                        " %02x %02x %02x %02x"
                                        " %02x %02x %02x %02x"
@@ -1163,18 +1163,18 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *))
                if (!rndis_per_dev_params [i].used) {
                        rndis_per_dev_params [i].used = 1;
                        rndis_per_dev_params [i].ack = rndis_control_ack;
-                       DEBUG("%s: configNr = %d\n", __FUNCTION__, i);
+                       DBG("%s: configNr = %d\n", __FUNCTION__, i);
                        return i;
                }
        }
-       DEBUG("failed\n");
+       DBG("failed\n");
 
        return -1;
 }
 
 void rndis_deregister (int configNr)
 {
-       DEBUG("%s: \n", __FUNCTION__ );
+       DBG("%s: \n", __FUNCTION__ );
 
        if (configNr >= RNDIS_MAX_CONFIGS) return;
        rndis_per_dev_params [configNr].used = 0;
@@ -1186,7 +1186,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
                         struct net_device_stats *stats,
                         u16 *cdc_filter)
 {
-       DEBUG("%s:\n", __FUNCTION__ );
+       DBG("%s:\n", __FUNCTION__ );
        if (!dev || !stats) return -1;
        if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
@@ -1199,7 +1199,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
 
 int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
 {
-       DEBUG("%s:\n", __FUNCTION__ );
+       DBG("%s:\n", __FUNCTION__ );
        if (!vendorDescr) return -1;
        if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
@@ -1211,7 +1211,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
 
 int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
 {
-       DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed);
+       DBG("%s: %u %u\n", __FUNCTION__, medium, speed);
        if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
        rndis_per_dev_params [configNr].medium = medium;
@@ -1390,7 +1390,7 @@ static int rndis_proc_write (struct file *file, const char __user *buffer,
                        break;
                default:
                        if (fl_speed) p->speed = speed;
-                       else DEBUG ("%c is not valid\n", c);
+                       else DBG("%c is not valid\n", c);
                        break;
                }
 
@@ -1419,12 +1419,12 @@ int __devinit rndis_init (void)
                if (!(rndis_connect_state [i]
                                = create_proc_entry (name, 0660, NULL)))
                {
-                       DEBUG ("%s :remove entries", __FUNCTION__);
+                       DBG("%s :remove entries", __FUNCTION__);
                        while (i) {
                                sprintf (name, NAME_TEMPLATE, --i);
                                remove_proc_entry (name, NULL);
                        }
-                       DEBUG ("\n");
+                       DBG("\n");
                        return -EIO;
                }
 
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
new file mode 100644 (file)
index 0000000..0be80c6
--- /dev/null
@@ -0,0 +1,2045 @@
+/*
+ * linux/drivers/usb/gadget/s3c2410_udc.c
+ *
+ * Samsung S3C24xx series on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
+ *     Additional cleanups by Ben Dooks <ben-linux@fluff.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include <linux/clk.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <linux/usb.h>
+#include <linux/usb_gadget.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/arch/irqs.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-udc.h>
+#include <asm/arch/udc.h>
+
+#include <asm/mach-types.h>
+
+#include "s3c2410_udc.h"
+
+#define DRIVER_DESC    "S3C2410 USB Device Controller Gadget"
+#define DRIVER_VERSION "29 Apr 2007"
+#define DRIVER_AUTHOR  "Herbert Pötzl <herbert@13thfloor.at>, " \
+                       "Arnaud Patard <arnaud.patard@rtp-net.org>"
+
+static const char              gadget_name[] = "s3c2410_udc";
+static const char              driver_desc[] = DRIVER_DESC;
+
+static struct s3c2410_udc      *the_controller;
+static struct clk              *udc_clock;
+static struct clk              *usb_bus_clock;
+static void __iomem            *base_addr;
+static u64                     rsrc_start;
+static u64                     rsrc_len;
+static struct dentry           *s3c2410_udc_debugfs_root;
+
+static inline u32 udc_read(u32 reg)
+{
+       return readb(base_addr + reg);
+}
+
+static inline void udc_write(u32 value, u32 reg)
+{
+       writeb(value, base_addr + reg);
+}
+
+static inline void udc_writeb(void __iomem *base, u32 value, u32 reg)
+{
+       writeb(value, base + reg);
+}
+
+static struct s3c2410_udc_mach_info *udc_info;
+
+/*************************** DEBUG FUNCTION ***************************/
+#define DEBUG_NORMAL   1
+#define DEBUG_VERBOSE  2
+
+#ifdef CONFIG_USB_S3C2410_DEBUG
+#define USB_S3C2410_DEBUG_LEVEL 0
+
+static uint32_t s3c2410_ticks = 0;
+
+static int dprintk(int level, const char *fmt, ...)
+{
+       static char printk_buf[1024];
+       static long prevticks;
+       static int invocation;
+       va_list args;
+       int len;
+
+       if (level > USB_S3C2410_DEBUG_LEVEL)
+               return 0;
+
+       if (s3c2410_ticks != prevticks) {
+               prevticks = s3c2410_ticks;
+               invocation = 0;
+       }
+
+       len = scnprintf(printk_buf,
+                       sizeof(printk_buf), "%1lu.%02d USB: ",
+                       prevticks, invocation++);
+
+       va_start(args, fmt);
+       len = vscnprintf(printk_buf+len,
+                       sizeof(printk_buf)-len, fmt, args);
+       va_end(args);
+
+       return printk(KERN_DEBUG "%s", printk_buf);
+}
+#else
+static int dprintk(int level, const char *fmt, ...)
+{
+       return 0;
+}
+#endif
+static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
+{
+       u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg;
+       u32 ep_int_en_reg, usb_int_en_reg, ep0_csr;
+       u32 ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2;
+       u32 ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2;
+
+       addr_reg       = udc_read(S3C2410_UDC_FUNC_ADDR_REG);
+       pwr_reg        = udc_read(S3C2410_UDC_PWR_REG);
+       ep_int_reg     = udc_read(S3C2410_UDC_EP_INT_REG);
+       usb_int_reg    = udc_read(S3C2410_UDC_USB_INT_REG);
+       ep_int_en_reg  = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+       usb_int_en_reg = udc_read(S3C2410_UDC_USB_INT_EN_REG);
+       udc_write(0, S3C2410_UDC_INDEX_REG);
+       ep0_csr        = udc_read(S3C2410_UDC_IN_CSR1_REG);
+       udc_write(1, S3C2410_UDC_INDEX_REG);
+       ep1_i_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+       ep1_i_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+       ep1_o_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+       ep1_o_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+       udc_write(2, S3C2410_UDC_INDEX_REG);
+       ep2_i_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+       ep2_i_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+       ep2_o_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+       ep2_o_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+
+       seq_printf(m, "FUNC_ADDR_REG  : 0x%04X\n"
+                "PWR_REG        : 0x%04X\n"
+                "EP_INT_REG     : 0x%04X\n"
+                "USB_INT_REG    : 0x%04X\n"
+                "EP_INT_EN_REG  : 0x%04X\n"
+                "USB_INT_EN_REG : 0x%04X\n"
+                "EP0_CSR        : 0x%04X\n"
+                "EP1_I_CSR1     : 0x%04X\n"
+                "EP1_I_CSR2     : 0x%04X\n"
+                "EP1_O_CSR1     : 0x%04X\n"
+                "EP1_O_CSR2     : 0x%04X\n"
+                "EP2_I_CSR1     : 0x%04X\n"
+                "EP2_I_CSR2     : 0x%04X\n"
+                "EP2_O_CSR1     : 0x%04X\n"
+                "EP2_O_CSR2     : 0x%04X\n",
+                       addr_reg,pwr_reg,ep_int_reg,usb_int_reg,
+                       ep_int_en_reg, usb_int_en_reg, ep0_csr,
+                       ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2,
+                       ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2
+               );
+
+       return 0;
+}
+
+static int s3c2410_udc_debugfs_fops_open(struct inode *inode,
+                                        struct file *file)
+{
+       return single_open(file, s3c2410_udc_debugfs_seq_show, NULL);
+}
+
+static const struct file_operations s3c2410_udc_debugfs_fops = {
+       .open           = s3c2410_udc_debugfs_fops_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .owner          = THIS_MODULE,
+};
+
+/* io macros */
+
+static inline void s3c2410_udc_clear_ep0_opr(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, S3C2410_UDC_EP0_CSR_SOPKTRDY,
+                       S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_clear_ep0_sst(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       writeb(0x00, base + S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_clear_ep0_se(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, S3C2410_UDC_EP0_CSR_SSE, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_ipr(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, S3C2410_UDC_EP0_CSR_IPKRDY, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, S3C2410_UDC_EP0_CSR_DE, S3C2410_UDC_EP0_CSR_REG);
+}
+
+inline void s3c2410_udc_set_ep0_ss(void __iomem *b)
+{
+       udc_writeb(b, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(b, S3C2410_UDC_EP0_CSR_SENDSTL, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+
+       udc_writeb(base,(S3C2410_UDC_EP0_CSR_SOPKTRDY
+                               | S3C2410_UDC_EP0_CSR_DE),
+                       S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_sse_out(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY
+                               | S3C2410_UDC_EP0_CSR_SSE),
+                       S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de_in(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, (S3C2410_UDC_EP0_CSR_IPKRDY
+                       | S3C2410_UDC_EP0_CSR_DE),
+               S3C2410_UDC_EP0_CSR_REG);
+}
+
+/*------------------------- I/O ----------------------------------*/
+
+/*
+ *     s3c2410_udc_done
+ */
+static void s3c2410_udc_done(struct s3c2410_ep *ep,
+               struct s3c2410_request *req, int status)
+{
+       unsigned halted = ep->halted;
+
+       list_del_init(&req->queue);
+
+       if (likely (req->req.status == -EINPROGRESS))
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       ep->halted = 1;
+       req->req.complete(&ep->ep, &req->req);
+       ep->halted = halted;
+}
+
+static void s3c2410_udc_nuke(struct s3c2410_udc *udc,
+               struct s3c2410_ep *ep, int status)
+{
+       /* Sanity check */
+       if (&ep->queue == NULL)
+               return;
+
+       while (!list_empty (&ep->queue)) {
+               struct s3c2410_request *req;
+               req = list_entry (ep->queue.next, struct s3c2410_request,
+                               queue);
+               s3c2410_udc_done(ep, req, status);
+       }
+}
+
+static inline void s3c2410_udc_clear_ep_state(struct s3c2410_udc *dev)
+{
+       unsigned i;
+
+       /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
+        * fifos, and pending transactions mustn't be continued in any case.
+        */
+
+       for (i = 1; i < S3C2410_ENDPOINTS; i++)
+               s3c2410_udc_nuke(dev, &dev->ep[i], -ECONNABORTED);
+}
+
+static inline int s3c2410_udc_fifo_count_out(void)
+{
+       int tmp;
+
+       tmp = udc_read(S3C2410_UDC_OUT_FIFO_CNT2_REG) << 8;
+       tmp |= udc_read(S3C2410_UDC_OUT_FIFO_CNT1_REG);
+       return tmp;
+}
+
+/*
+ *     s3c2410_udc_write_packet
+ */
+static inline int s3c2410_udc_write_packet(int fifo,
+               struct s3c2410_request *req,
+               unsigned max)
+{
+       unsigned len = min(req->req.length - req->req.actual, max);
+       u8 *buf = req->req.buf + req->req.actual;
+
+       prefetch(buf);
+
+       dprintk(DEBUG_VERBOSE, "%s %d %d %d %d\n", __func__,
+               req->req.actual, req->req.length, len, req->req.actual + len);
+
+       req->req.actual += len;
+
+       udelay(5);
+       writesb(base_addr + fifo, buf, len);
+       return len;
+}
+
+/*
+ *     s3c2410_udc_write_fifo
+ *
+ * return:  0 = still running, 1 = completed, negative = errno
+ */
+static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep,
+               struct s3c2410_request *req)
+{
+       unsigned        count;
+       int             is_last;
+       u32             idx;
+       int             fifo_reg;
+       u32             ep_csr;
+
+       idx = ep->bEndpointAddress & 0x7F;
+       switch (idx) {
+       default:
+               idx = 0;
+       case 0:
+               fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
+               break;
+       case 1:
+               fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
+               break;
+       case 2:
+               fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
+               break;
+       case 3:
+               fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
+               break;
+       case 4:
+               fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
+               break;
+       }
+
+       count = s3c2410_udc_write_packet(fifo_reg, req, ep->ep.maxpacket);
+
+       /* last packet is often short (sometimes a zlp) */
+       if (count != ep->ep.maxpacket)
+               is_last = 1;
+       else if (req->req.length != req->req.actual || req->req.zero)
+               is_last = 0;
+       else
+               is_last = 2;
+
+       /* Only ep0 debug messages are interesting */
+       if (idx == 0)
+               dprintk(DEBUG_NORMAL,
+                       "Written ep%d %d.%d of %d b [last %d,z %d]\n",
+                       idx, count, req->req.actual, req->req.length,
+                       is_last, req->req.zero);
+
+       if (is_last) {
+               /* The order is important. It prevents sending 2 packets
+                * at the same time */
+
+               if (idx == 0) {
+                       /* Reset signal => no need to say 'data sent' */
+                       if (! (udc_read(S3C2410_UDC_USB_INT_REG)
+                                       & S3C2410_UDC_USBINT_RESET))
+                               s3c2410_udc_set_ep0_de_in(base_addr);
+                       ep->dev->ep0state=EP0_IDLE;
+               } else {
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
+                                       S3C2410_UDC_IN_CSR1_REG);
+               }
+
+               s3c2410_udc_done(ep, req, 0);
+               is_last = 1;
+       } else {
+               if (idx == 0) {
+                       /* Reset signal => no need to say 'data sent' */
+                       if (! (udc_read(S3C2410_UDC_USB_INT_REG)
+                                       & S3C2410_UDC_USBINT_RESET))
+                               s3c2410_udc_set_ep0_ipr(base_addr);
+               } else {
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
+                                       S3C2410_UDC_IN_CSR1_REG);
+               }
+       }
+
+       return is_last;
+}
+
+static inline int s3c2410_udc_read_packet(int fifo, u8 *buf,
+               struct s3c2410_request *req, unsigned avail)
+{
+       unsigned len;
+
+       len = min(req->req.length - req->req.actual, avail);
+       req->req.actual += len;
+
+       readsb(fifo + base_addr, buf, len);
+       return len;
+}
+
+/*
+ * return:  0 = still running, 1 = queue empty, negative = errno
+ */
+static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep,
+                                struct s3c2410_request *req)
+{
+       u8              *buf;
+       u32             ep_csr;
+       unsigned        bufferspace;
+       int             is_last=1;
+       unsigned        avail;
+       int             fifo_count = 0;
+       u32             idx;
+       int             fifo_reg;
+
+       idx = ep->bEndpointAddress & 0x7F;
+
+       switch (idx) {
+       default:
+               idx = 0;
+       case 0:
+               fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
+               break;
+       case 1:
+               fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
+               break;
+       case 2:
+               fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
+               break;
+       case 3:
+               fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
+               break;
+       case 4:
+               fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
+               break;
+       }
+
+       if (!req->req.length)
+               return 1;
+
+       buf = req->req.buf + req->req.actual;
+       bufferspace = req->req.length - req->req.actual;
+       if (!bufferspace) {
+               dprintk(DEBUG_NORMAL, "%s: buffer full!\n", __func__);
+               return -1;
+       }
+
+       udc_write(idx, S3C2410_UDC_INDEX_REG);
+
+       fifo_count = s3c2410_udc_fifo_count_out();
+       dprintk(DEBUG_NORMAL, "%s fifo count : %d\n", __func__, fifo_count);
+
+       if (fifo_count > ep->ep.maxpacket)
+               avail = ep->ep.maxpacket;
+       else
+               avail = fifo_count;
+
+       fifo_count = s3c2410_udc_read_packet(fifo_reg, buf, req, avail);
+
+       /* checking this with ep0 is not accurate as we already
+        * read a control request
+        **/
+       if (idx != 0 && fifo_count < ep->ep.maxpacket) {
+               is_last = 1;
+               /* overflowed this request?  flush extra data */
+               if (fifo_count != avail)
+                       req->req.status = -EOVERFLOW;
+       } else {
+               is_last = (req->req.length <= req->req.actual) ? 1 : 0;
+       }
+
+       udc_write(idx, S3C2410_UDC_INDEX_REG);
+       fifo_count = s3c2410_udc_fifo_count_out();
+
+       /* Only ep0 debug messages are interesting */
+       if (idx == 0)
+               dprintk(DEBUG_VERBOSE, "%s fifo count : %d [last %d]\n",
+                       __func__, fifo_count,is_last);
+
+       if (is_last) {
+               if (idx == 0) {
+                       s3c2410_udc_set_ep0_de_out(base_addr);
+                       ep->dev->ep0state = EP0_IDLE;
+               } else {
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
+                                       S3C2410_UDC_OUT_CSR1_REG);
+               }
+
+               s3c2410_udc_done(ep, req, 0);
+       } else {
+               if (idx == 0) {
+                       s3c2410_udc_clear_ep0_opr(base_addr);
+               } else {
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
+                                       S3C2410_UDC_OUT_CSR1_REG);
+               }
+       }
+
+       return is_last;
+}
+
+static int s3c2410_udc_read_fifo_crq(struct usb_ctrlrequest *crq)
+{
+       unsigned char *outbuf = (unsigned char*)crq;
+       int bytes_read = 0;
+
+       udc_write(0, S3C2410_UDC_INDEX_REG);
+
+       bytes_read = s3c2410_udc_fifo_count_out();
+
+       dprintk(DEBUG_NORMAL, "%s: fifo_count=%d\n", __func__, bytes_read);
+
+       if (bytes_read > sizeof(struct usb_ctrlrequest))
+               bytes_read = sizeof(struct usb_ctrlrequest);
+
+       readsb(S3C2410_UDC_EP0_FIFO_REG + base_addr, outbuf, bytes_read);
+
+       dprintk(DEBUG_VERBOSE, "%s: len=%d %02x:%02x {%x,%x,%x}\n", __func__,
+               bytes_read, crq->bRequest, crq->bRequestType,
+               crq->wValue, crq->wIndex, crq->wLength);
+
+       return bytes_read;
+}
+
+static int s3c2410_udc_get_status(struct s3c2410_udc *dev,
+               struct usb_ctrlrequest *crq)
+{
+       u16 status = 0;
+       u8 ep_num = crq->wIndex & 0x7F;
+       u8 is_in = crq->wIndex & USB_DIR_IN;
+
+       switch (crq->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_INTERFACE:
+               break;
+
+       case USB_RECIP_DEVICE:
+               status = dev->devstatus;
+               break;
+
+       case USB_RECIP_ENDPOINT:
+               if (ep_num > 4 || crq->wLength > 2)
+                       return 1;
+
+               if (ep_num == 0) {
+                       udc_write(0, S3C2410_UDC_INDEX_REG);
+                       status = udc_read(S3C2410_UDC_IN_CSR1_REG);
+                       status = status & S3C2410_UDC_EP0_CSR_SENDSTL;
+               } else {
+                       udc_write(ep_num, S3C2410_UDC_INDEX_REG);
+                       if (is_in) {
+                               status = udc_read(S3C2410_UDC_IN_CSR1_REG);
+                               status = status & S3C2410_UDC_ICSR1_SENDSTL;
+                       } else {
+                               status = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+                               status = status & S3C2410_UDC_OCSR1_SENDSTL;
+                       }
+               }
+
+               status = status ? 1 : 0;
+               break;
+
+       default:
+               return 1;
+       }
+
+       /* Seems to be needed to get it working. ouch :( */
+       udelay(5);
+       udc_write(status & 0xFF, S3C2410_UDC_EP0_FIFO_REG);
+       udc_write(status >> 8, S3C2410_UDC_EP0_FIFO_REG);
+       s3c2410_udc_set_ep0_de_in(base_addr);
+
+       return 0;
+}
+/*------------------------- usb state machine -------------------------------*/
+static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value);
+
+static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
+                                       struct s3c2410_ep *ep,
+                                       struct usb_ctrlrequest *crq,
+                                       u32 ep0csr)
+{
+       int len, ret, tmp;
+
+       /* start control request? */
+       if (!(ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY))
+               return;
+
+       s3c2410_udc_nuke(dev, ep, -EPROTO);
+
+       len = s3c2410_udc_read_fifo_crq(crq);
+       if (len != sizeof(*crq)) {
+               dprintk(DEBUG_NORMAL, "setup begin: fifo READ ERROR"
+                       " wanted %d bytes got %d. Stalling out...\n",
+                       sizeof(*crq), len);
+               s3c2410_udc_set_ep0_ss(base_addr);
+               return;
+       }
+
+       dprintk(DEBUG_NORMAL, "bRequest = %d bRequestType %d wLength = %d\n",
+               crq->bRequest, crq->bRequestType, crq->wLength);
+
+       /* cope with automagic for some standard requests. */
+       dev->req_std = (crq->bRequestType & USB_TYPE_MASK)
+               == USB_TYPE_STANDARD;
+       dev->req_config = 0;
+       dev->req_pending = 1;
+
+       switch (crq->bRequest) {
+       case USB_REQ_SET_CONFIGURATION:
+               dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ... \n");
+
+               if (crq->bRequestType == USB_RECIP_DEVICE) {
+                       dev->req_config = 1;
+                       s3c2410_udc_set_ep0_de_out(base_addr);
+               }
+               break;
+
+       case USB_REQ_SET_INTERFACE:
+               dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ... \n");
+
+               if (crq->bRequestType == USB_RECIP_INTERFACE) {
+                       dev->req_config = 1;
+                       s3c2410_udc_set_ep0_de_out(base_addr);
+               }
+               break;
+
+       case USB_REQ_SET_ADDRESS:
+               dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ... \n");
+
+               if (crq->bRequestType == USB_RECIP_DEVICE) {
+                       tmp = crq->wValue & 0x7F;
+                       dev->address = tmp;
+                       udc_write((tmp | S3C2410_UDC_FUNCADDR_UPDATE),
+                                       S3C2410_UDC_FUNC_ADDR_REG);
+                       s3c2410_udc_set_ep0_de_out(base_addr);
+                       return;
+               }
+               break;
+
+       case USB_REQ_GET_STATUS:
+               dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ... \n");
+               s3c2410_udc_clear_ep0_opr(base_addr);
+
+               if (dev->req_std) {
+                       if (!s3c2410_udc_get_status(dev, crq)) {
+                               return;
+                       }
+               }
+               break;
+
+       case USB_REQ_CLEAR_FEATURE:
+               s3c2410_udc_clear_ep0_opr(base_addr);
+
+               if (crq->bRequestType != USB_RECIP_ENDPOINT)
+                       break;
+
+               if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
+                       break;
+
+               s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 0);
+               s3c2410_udc_set_ep0_de_out(base_addr);
+               return;
+
+       case USB_REQ_SET_FEATURE:
+               s3c2410_udc_clear_ep0_opr(base_addr);
+
+               if (crq->bRequestType != USB_RECIP_ENDPOINT)
+                       break;
+
+               if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
+                       break;
+
+               s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 1);
+               s3c2410_udc_set_ep0_de_out(base_addr);
+               return;
+
+       default:
+               s3c2410_udc_clear_ep0_opr(base_addr);
+               break;
+       }
+
+       if (crq->bRequestType & USB_DIR_IN)
+               dev->ep0state = EP0_IN_DATA_PHASE;
+       else
+               dev->ep0state = EP0_OUT_DATA_PHASE;
+
+       ret = dev->driver->setup(&dev->gadget, crq);
+       if (ret < 0) {
+               if (dev->req_config) {
+                       dprintk(DEBUG_NORMAL, "config change %02x fail %d?\n",
+                               crq->bRequest, ret);
+                       return;
+               }
+
+               if (ret == -EOPNOTSUPP)
+                       dprintk(DEBUG_NORMAL, "Operation not supported\n");
+               else
+                       dprintk(DEBUG_NORMAL,
+                               "dev->driver->setup failed. (%d)\n", ret);
+
+               udelay(5);
+               s3c2410_udc_set_ep0_ss(base_addr);
+               s3c2410_udc_set_ep0_de_out(base_addr);
+               dev->ep0state = EP0_IDLE;
+               /* deferred i/o == no response yet */
+       } else if (dev->req_pending) {
+               dprintk(DEBUG_VERBOSE, "dev->req_pending... what now?\n");
+               dev->req_pending=0;
+       }
+
+       dprintk(DEBUG_VERBOSE, "ep0state %s\n", ep0states[dev->ep0state]);
+}
+
+static void s3c2410_udc_handle_ep0(struct s3c2410_udc *dev)
+{
+       u32                     ep0csr;
+       struct s3c2410_ep       *ep = &dev->ep[0];
+       struct s3c2410_request  *req;
+       struct usb_ctrlrequest  crq;
+
+       if (list_empty(&ep->queue))
+               req = NULL;
+       else
+               req = list_entry(ep->queue.next, struct s3c2410_request, queue);
+
+       /* We make the assumption that S3C2410_UDC_IN_CSR1_REG equal to
+        * S3C2410_UDC_EP0_CSR_REG when index is zero */
+
+       udc_write(0, S3C2410_UDC_INDEX_REG);
+       ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+
+       dprintk(DEBUG_NORMAL, "ep0csr %x ep0state %s\n",
+               ep0csr, ep0states[dev->ep0state]);
+
+       /* clear stall status */
+       if (ep0csr & S3C2410_UDC_EP0_CSR_SENTSTL) {
+               s3c2410_udc_nuke(dev, ep, -EPIPE);
+               dprintk(DEBUG_NORMAL, "... clear SENT_STALL ...\n");
+               s3c2410_udc_clear_ep0_sst(base_addr);
+               dev->ep0state = EP0_IDLE;
+               return;
+       }
+
+       /* clear setup end */
+       if (ep0csr & S3C2410_UDC_EP0_CSR_SE) {
+               dprintk(DEBUG_NORMAL, "... serviced SETUP_END ...\n");
+               s3c2410_udc_nuke(dev, ep, 0);
+               s3c2410_udc_clear_ep0_se(base_addr);
+               dev->ep0state = EP0_IDLE;
+       }
+
+       switch (dev->ep0state) {
+       case EP0_IDLE:
+               s3c2410_udc_handle_ep0_idle(dev, ep, &crq, ep0csr);
+               break;
+
+       case EP0_IN_DATA_PHASE:                 /* GET_DESCRIPTOR etc */
+               dprintk(DEBUG_NORMAL, "EP0_IN_DATA_PHASE ... what now?\n");
+               if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req) {
+                       s3c2410_udc_write_fifo(ep, req);
+               }
+               break;
+
+       case EP0_OUT_DATA_PHASE:                /* SET_DESCRIPTOR etc */
+               dprintk(DEBUG_NORMAL, "EP0_OUT_DATA_PHASE ... what now?\n");
+               if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req ) {
+                       s3c2410_udc_read_fifo(ep,req);
+               }
+               break;
+
+       case EP0_END_XFER:
+               dprintk(DEBUG_NORMAL, "EP0_END_XFER ... what now?\n");
+               dev->ep0state = EP0_IDLE;
+               break;
+
+       case EP0_STALL:
+               dprintk(DEBUG_NORMAL, "EP0_STALL ... what now?\n");
+               dev->ep0state = EP0_IDLE;
+               break;
+       }
+}
+
+/*
+ *     handle_ep - Manage I/O endpoints
+ */
+
+static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
+{
+       struct s3c2410_request  *req;
+       int                     is_in = ep->bEndpointAddress & USB_DIR_IN;
+       u32                     ep_csr1;
+       u32                     idx;
+
+       if (likely (!list_empty(&ep->queue)))
+               req = list_entry(ep->queue.next,
+                               struct s3c2410_request, queue);
+       else
+               req = NULL;
+
+       idx = ep->bEndpointAddress & 0x7F;
+
+       if (is_in) {
+               udc_write(idx, S3C2410_UDC_INDEX_REG);
+               ep_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
+               dprintk(DEBUG_VERBOSE, "ep%01d write csr:%02x %d\n",
+                       idx, ep_csr1, req ? 1 : 0);
+
+               if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) {
+                       dprintk(DEBUG_VERBOSE, "st\n");
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr1 & ~S3C2410_UDC_ICSR1_SENTSTL,
+                                       S3C2410_UDC_IN_CSR1_REG);
+                       return;
+               }
+
+               if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req) {
+                       s3c2410_udc_write_fifo(ep,req);
+               }
+       } else {
+               udc_write(idx, S3C2410_UDC_INDEX_REG);
+               ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+               dprintk(DEBUG_VERBOSE, "ep%01d rd csr:%02x\n", idx, ep_csr1);
+
+               if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) {
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr1 & ~S3C2410_UDC_OCSR1_SENTSTL,
+                                       S3C2410_UDC_OUT_CSR1_REG);
+                       return;
+               }
+
+               if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
+                       s3c2410_udc_read_fifo(ep,req);
+               }
+       }
+}
+
+#include <asm/arch/regs-irq.h>
+
+/*
+ *     s3c2410_udc_irq - interrupt handler
+ */
+static irqreturn_t s3c2410_udc_irq(int irq, void *_dev)
+{
+       struct s3c2410_udc *dev = _dev;
+       int usb_status;
+       int usbd_status;
+       int pwr_reg;
+       int ep0csr;
+       int i;
+       u32 idx;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       /* Driver connected ? */
+       if (!dev->driver) {
+               /* Clear interrupts */
+               udc_write(udc_read(S3C2410_UDC_USB_INT_REG),
+                               S3C2410_UDC_USB_INT_REG);
+               udc_write(udc_read(S3C2410_UDC_EP_INT_REG),
+                               S3C2410_UDC_EP_INT_REG);
+       }
+
+       /* Save index */
+       idx = udc_read(S3C2410_UDC_INDEX_REG);
+
+       /* Read status registers */
+       usb_status = udc_read(S3C2410_UDC_USB_INT_REG);
+       usbd_status = udc_read(S3C2410_UDC_EP_INT_REG);
+       pwr_reg = udc_read(S3C2410_UDC_PWR_REG);
+
+       udc_writeb(base_addr, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+
+       dprintk(DEBUG_NORMAL, "usbs=%02x, usbds=%02x, pwr=%02x ep0csr=%02x\n",
+               usb_status, usbd_status, pwr_reg, ep0csr);
+
+       /*
+        * Now, handle interrupts. There's two types :
+        * - Reset, Resume, Suspend coming -> usb_int_reg
+        * - EP -> ep_int_reg
+        */
+
+       /* RESET */
+       if (usb_status & S3C2410_UDC_USBINT_RESET) {
+               /* two kind of reset :
+                * - reset start -> pwr reg = 8
+                * - reset end   -> pwr reg = 0
+                **/
+               dprintk(DEBUG_NORMAL, "USB reset csr %x pwr %x\n",
+                       ep0csr, pwr_reg);
+
+               dev->gadget.speed = USB_SPEED_UNKNOWN;
+               udc_write(0x00, S3C2410_UDC_INDEX_REG);
+               udc_write((dev->ep[0].ep.maxpacket & 0x7ff) >> 3,
+                               S3C2410_UDC_MAXP_REG);
+               dev->address = 0;
+
+               dev->ep0state = EP0_IDLE;
+               dev->gadget.speed = USB_SPEED_FULL;
+
+               /* clear interrupt */
+               udc_write(S3C2410_UDC_USBINT_RESET,
+                               S3C2410_UDC_USB_INT_REG);
+
+               udc_write(idx, S3C2410_UDC_INDEX_REG);
+               spin_unlock_irqrestore(&dev->lock, flags);
+               return IRQ_HANDLED;
+       }
+
+       /* RESUME */
+       if (usb_status & S3C2410_UDC_USBINT_RESUME) {
+               dprintk(DEBUG_NORMAL, "USB resume\n");
+
+               /* clear interrupt */
+               udc_write(S3C2410_UDC_USBINT_RESUME,
+                               S3C2410_UDC_USB_INT_REG);
+
+               if (dev->gadget.speed != USB_SPEED_UNKNOWN
+                               && dev->driver
+                               && dev->driver->resume)
+                       dev->driver->resume(&dev->gadget);
+       }
+
+       /* SUSPEND */
+       if (usb_status & S3C2410_UDC_USBINT_SUSPEND) {
+               dprintk(DEBUG_NORMAL, "USB suspend\n");
+
+               /* clear interrupt */
+               udc_write(S3C2410_UDC_USBINT_SUSPEND,
+                               S3C2410_UDC_USB_INT_REG);
+
+               if (dev->gadget.speed != USB_SPEED_UNKNOWN
+                               && dev->driver
+                               && dev->driver->suspend)
+                       dev->driver->suspend(&dev->gadget);
+
+               dev->ep0state = EP0_IDLE;
+       }
+
+       /* EP */
+       /* control traffic */
+       /* check on ep0csr != 0 is not a good idea as clearing in_pkt_ready
+        * generate an interrupt
+        */
+       if (usbd_status & S3C2410_UDC_INT_EP0) {
+               dprintk(DEBUG_VERBOSE, "USB ep0 irq\n");
+               /* Clear the interrupt bit by setting it to 1 */
+               udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);
+               s3c2410_udc_handle_ep0(dev);
+       }
+
+       /* endpoint data transfers */
+       for (i = 1; i < S3C2410_ENDPOINTS; i++) {
+               u32 tmp = 1 << i;
+               if (usbd_status & tmp) {
+                       dprintk(DEBUG_VERBOSE, "USB ep%d irq\n", i);
+
+                       /* Clear the interrupt bit by setting it to 1 */
+                       udc_write(tmp, S3C2410_UDC_EP_INT_REG);
+                       s3c2410_udc_handle_ep(&dev->ep[i]);
+               }
+       }
+
+       dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", irq);
+
+       /* Restore old index */
+       udc_write(idx, S3C2410_UDC_INDEX_REG);
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return IRQ_HANDLED;
+}
+/*------------------------- s3c2410_ep_ops ----------------------------------*/
+
+static inline struct s3c2410_ep *to_s3c2410_ep(struct usb_ep *ep)
+{
+       return container_of(ep, struct s3c2410_ep, ep);
+}
+
+static inline struct s3c2410_udc *to_s3c2410_udc(struct usb_gadget *gadget)
+{
+       return container_of(gadget, struct s3c2410_udc, gadget);
+}
+
+static inline struct s3c2410_request *to_s3c2410_req(struct usb_request *req)
+{
+       return container_of(req, struct s3c2410_request, req);
+}
+
+/*
+ *     s3c2410_udc_ep_enable
+ */
+static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
+                                const struct usb_endpoint_descriptor *desc)
+{
+       struct s3c2410_udc      *dev;
+       struct s3c2410_ep       *ep;
+       u32                     max, tmp;
+       unsigned long           flags;
+       u32                     csr1,csr2;
+       u32                     int_en_reg;
+
+       ep = to_s3c2410_ep(_ep);
+
+       if (!_ep || !desc || ep->desc
+                       || _ep->name == ep0name
+                       || desc->bDescriptorType != USB_DT_ENDPOINT)
+               return -EINVAL;
+
+       dev = ep->dev;
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff;
+
+       local_irq_save (flags);
+       _ep->maxpacket = max & 0x7ff;
+       ep->desc = desc;
+       ep->halted = 0;
+       ep->bEndpointAddress = desc->bEndpointAddress;
+
+       /* set max packet */
+       udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+       udc_write(max >> 3, S3C2410_UDC_MAXP_REG);
+
+       /* set type, direction, address; reset fifo counters */
+       if (desc->bEndpointAddress & USB_DIR_IN) {
+               csr1 = S3C2410_UDC_ICSR1_FFLUSH|S3C2410_UDC_ICSR1_CLRDT;
+               csr2 = S3C2410_UDC_ICSR2_MODEIN|S3C2410_UDC_ICSR2_DMAIEN;
+
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
+       } else {
+               /* don't flush in fifo or it will cause endpoint interrupt */
+               csr1 = S3C2410_UDC_ICSR1_CLRDT;
+               csr2 = S3C2410_UDC_ICSR2_DMAIEN;
+
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
+
+               csr1 = S3C2410_UDC_OCSR1_FFLUSH | S3C2410_UDC_OCSR1_CLRDT;
+               csr2 = S3C2410_UDC_OCSR2_DMAIEN;
+
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr1, S3C2410_UDC_OUT_CSR1_REG);
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr2, S3C2410_UDC_OUT_CSR2_REG);
+       }
+
+       /* enable irqs */
+       int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+       udc_write(int_en_reg | (1 << ep->num), S3C2410_UDC_EP_INT_EN_REG);
+
+       /* print some debug message */
+       tmp = desc->bEndpointAddress;
+       dprintk (DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n",
+                _ep->name,ep->num, tmp,
+                desc->bEndpointAddress & USB_DIR_IN ? "in" : "out", max);
+
+       local_irq_restore (flags);
+       s3c2410_udc_set_halt(_ep, 0);
+
+       return 0;
+}
+
+/*
+ * s3c2410_udc_ep_disable
+ */
+static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
+{
+       struct s3c2410_ep *ep = to_s3c2410_ep(_ep);
+       unsigned long flags;
+       u32 int_en_reg;
+
+       if (!_ep || !ep->desc) {
+               dprintk(DEBUG_NORMAL, "%s not enabled\n",
+                       _ep ? ep->ep.name : NULL);
+               return -EINVAL;
+       }
+
+       local_irq_save(flags);
+
+       dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
+
+       ep->desc = NULL;
+       ep->halted = 1;
+
+       s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN);
+
+       /* disable irqs */
+       int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+       udc_write(int_en_reg & ~(1<<ep->num), S3C2410_UDC_EP_INT_EN_REG);
+
+       local_irq_restore(flags);
+
+       dprintk(DEBUG_NORMAL, "%s disabled\n", _ep->name);
+
+       return 0;
+}
+
+/*
+ * s3c2410_udc_alloc_request
+ */
+static struct usb_request *
+s3c2410_udc_alloc_request(struct usb_ep *_ep, gfp_t mem_flags)
+{
+       struct s3c2410_request *req;
+
+       dprintk(DEBUG_VERBOSE,"%s(%p,%d)\n", __func__, _ep, mem_flags);
+
+       if (!_ep)
+               return NULL;
+
+       req = kzalloc (sizeof(struct s3c2410_request), mem_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD (&req->queue);
+       return &req->req;
+}
+
+/*
+ * s3c2410_udc_free_request
+ */
+static void
+s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
+       struct s3c2410_request  *req = to_s3c2410_req(_req);
+
+       dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
+
+       if (!ep || !_req || (!ep->desc && _ep->name != ep0name))
+               return;
+
+       WARN_ON (!list_empty (&req->queue));
+       kfree(req);
+}
+
+/*
+ *     s3c2410_udc_queue
+ */
+static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req,
+               gfp_t gfp_flags)
+{
+       struct s3c2410_request  *req = to_s3c2410_req(_req);
+       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
+       struct s3c2410_udc      *dev;
+       u32                     ep_csr = 0;
+       int                     fifo_count = 0;
+       unsigned long           flags;
+
+       if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+               dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__);
+               return -EINVAL;
+       }
+
+       dev = ep->dev;
+       if (unlikely (!dev->driver
+                       || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+               return -ESHUTDOWN;
+       }
+
+       local_irq_save (flags);
+
+       if (unlikely(!_req || !_req->complete
+                       || !_req->buf || !list_empty(&req->queue))) {
+               if (!_req)
+                       dprintk(DEBUG_NORMAL, "%s: 1 X X X\n", __func__);
+               else {
+                       dprintk(DEBUG_NORMAL, "%s: 0 %01d %01d %01d\n",
+                               __func__, !_req->complete,!_req->buf,
+                               !list_empty(&req->queue));
+               }
+
+               local_irq_restore(flags);
+               return -EINVAL;
+       }
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       dprintk(DEBUG_VERBOSE, "%s: ep%x len %d\n",
+                __func__, ep->bEndpointAddress, _req->length);
+
+       if (ep->bEndpointAddress) {
+               udc_write(ep->bEndpointAddress & 0x7F, S3C2410_UDC_INDEX_REG);
+
+               ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN)
+                               ? S3C2410_UDC_IN_CSR1_REG
+                               : S3C2410_UDC_OUT_CSR1_REG);
+               fifo_count = s3c2410_udc_fifo_count_out();
+       } else {
+               udc_write(0, S3C2410_UDC_INDEX_REG);
+               ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+               fifo_count = s3c2410_udc_fifo_count_out();
+       }
+
+       /* kickstart this i/o queue? */
+       if (list_empty(&ep->queue) && !ep->halted) {
+               if (ep->bEndpointAddress == 0 /* ep0 */) {
+                       switch (dev->ep0state) {
+                       case EP0_IN_DATA_PHASE:
+                               if (!(ep_csr&S3C2410_UDC_EP0_CSR_IPKRDY)
+                                               && s3c2410_udc_write_fifo(ep,
+                                                       req)) {
+                                       dev->ep0state = EP0_IDLE;
+                                       req = NULL;
+                               }
+                               break;
+
+                       case EP0_OUT_DATA_PHASE:
+                               if ((!_req->length)
+                                       || ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
+                                               && s3c2410_udc_read_fifo(ep,
+                                                       req))) {
+                                       dev->ep0state = EP0_IDLE;
+                                       req = NULL;
+                               }
+                               break;
+
+                       default:
+                               local_irq_restore(flags);
+                               return -EL2HLT;
+                       }
+               } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0
+                               && (!(ep_csr&S3C2410_UDC_OCSR1_PKTRDY))
+                               && s3c2410_udc_write_fifo(ep, req)) {
+                       req = NULL;
+               } else if ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
+                               && fifo_count
+                               && s3c2410_udc_read_fifo(ep, req)) {
+                       req = NULL;
+               }
+       }
+
+       /* pio or dma irq handler advances the queue. */
+       if (likely (req != 0))
+               list_add_tail(&req->queue, &ep->queue);
+
+       local_irq_restore(flags);
+
+       dprintk(DEBUG_VERBOSE, "%s ok\n", __func__);
+       return 0;
+}
+
+/*
+ *     s3c2410_udc_dequeue
+ */
+static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
+       struct s3c2410_udc      *udc;
+       int                     retval = -EINVAL;
+       unsigned long           flags;
+       struct s3c2410_request  *req = NULL;
+
+       dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
+
+       if (!the_controller->driver)
+               return -ESHUTDOWN;
+
+       if (!_ep || !_req)
+               return retval;
+
+       udc = to_s3c2410_udc(ep->gadget);
+
+       local_irq_save (flags);
+
+       list_for_each_entry (req, &ep->queue, queue) {
+               if (&req->req == _req) {
+                       list_del_init (&req->queue);
+                       _req->status = -ECONNRESET;
+                       retval = 0;
+                       break;
+               }
+       }
+
+       if (retval == 0) {
+               dprintk(DEBUG_VERBOSE,
+                       "dequeued req %p from %s, len %d buf %p\n",
+                       req, _ep->name, _req->length, _req->buf);
+
+               s3c2410_udc_done(ep, req, -ECONNRESET);
+       }
+
+       local_irq_restore (flags);
+       return retval;
+}
+
+/*
+ * s3c2410_udc_set_halt
+ */
+static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value)
+{
+       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
+       u32                     ep_csr = 0;
+       unsigned long           flags;
+       u32                     idx;
+
+       if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+               dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__);
+               return -EINVAL;
+       }
+
+       local_irq_save (flags);
+
+       idx = ep->bEndpointAddress & 0x7F;
+
+       if (idx == 0) {
+               s3c2410_udc_set_ep0_ss(base_addr);
+               s3c2410_udc_set_ep0_de_out(base_addr);
+       } else {
+               udc_write(idx, S3C2410_UDC_INDEX_REG);
+               ep_csr = udc_read((ep->bEndpointAddress &USB_DIR_IN)
+                               ? S3C2410_UDC_IN_CSR1_REG
+                               : S3C2410_UDC_OUT_CSR1_REG);
+
+               if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
+                       if (value)
+                               udc_write(ep_csr | S3C2410_UDC_ICSR1_SENDSTL,
+                                       S3C2410_UDC_IN_CSR1_REG);
+                       else {
+                               ep_csr &= ~S3C2410_UDC_ICSR1_SENDSTL;
+                               udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
+                               ep_csr |= S3C2410_UDC_ICSR1_CLRDT;
+                               udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
+                       }
+               } else {
+                       if (value)
+                               udc_write(ep_csr | S3C2410_UDC_OCSR1_SENDSTL,
+                                       S3C2410_UDC_OUT_CSR1_REG);
+                       else {
+                               ep_csr &= ~S3C2410_UDC_OCSR1_SENDSTL;
+                               udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
+                               ep_csr |= S3C2410_UDC_OCSR1_CLRDT;
+                               udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
+                       }
+               }
+       }
+
+       ep->halted = value ? 1 : 0;
+       local_irq_restore (flags);
+
+       return 0;
+}
+
+static const struct usb_ep_ops s3c2410_ep_ops = {
+       .enable         = s3c2410_udc_ep_enable,
+       .disable        = s3c2410_udc_ep_disable,
+
+       .alloc_request  = s3c2410_udc_alloc_request,
+       .free_request   = s3c2410_udc_free_request,
+
+       .queue          = s3c2410_udc_queue,
+       .dequeue        = s3c2410_udc_dequeue,
+
+       .set_halt       = s3c2410_udc_set_halt,
+};
+
+/*------------------------- usb_gadget_ops ----------------------------------*/
+
+/*
+ *     s3c2410_udc_get_frame
+ */
+static int s3c2410_udc_get_frame(struct usb_gadget *_gadget)
+{
+       int tmp;
+
+       dprintk(DEBUG_VERBOSE, "%s()\n", __func__);
+
+       tmp = udc_read(S3C2410_UDC_FRAME_NUM2_REG) << 8;
+       tmp |= udc_read(S3C2410_UDC_FRAME_NUM1_REG);
+       return tmp;
+}
+
+/*
+ *     s3c2410_udc_wakeup
+ */
+static int s3c2410_udc_wakeup(struct usb_gadget *_gadget)
+{
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+       return 0;
+}
+
+/*
+ *     s3c2410_udc_set_selfpowered
+ */
+static int s3c2410_udc_set_selfpowered(struct usb_gadget *gadget, int value)
+{
+       struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       if (value)
+               udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
+       else
+               udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
+
+       return 0;
+}
+
+static void s3c2410_udc_disable(struct s3c2410_udc *dev);
+static void s3c2410_udc_enable(struct s3c2410_udc *dev);
+
+static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on)
+{
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       if (udc_info && udc_info->udc_command) {
+               if (is_on)
+                       s3c2410_udc_enable(udc);
+               else {
+                       if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+                               if (udc->driver && udc->driver->disconnect)
+                                       udc->driver->disconnect(&udc->gadget);
+
+                       }
+                       s3c2410_udc_disable(udc);
+               }
+       }
+       else
+               return -EOPNOTSUPP;
+
+       return 0;
+}
+
+static int s3c2410_udc_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       udc->vbus = (is_active != 0);
+       s3c2410_udc_set_pullup(udc, is_active);
+       return 0;
+}
+
+static int s3c2410_udc_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       s3c2410_udc_set_pullup(udc, is_on ? 0 : 1);
+       return 0;
+}
+
+static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev)
+{
+       struct s3c2410_udc      *dev = _dev;
+       unsigned int            value;
+
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+       value = s3c2410_gpio_getpin(udc_info->vbus_pin);
+
+       if (udc_info->vbus_pin_inverted)
+               value = !value;
+
+       if (value != dev->vbus)
+               s3c2410_udc_vbus_session(&dev->gadget, value);
+
+       return IRQ_HANDLED;
+}
+
+static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
+{
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       if (udc_info && udc_info->vbus_draw) {
+               udc_info->vbus_draw(ma);
+               return 0;
+       }
+
+       return -ENOTSUPP;
+}
+
+static const struct usb_gadget_ops s3c2410_ops = {
+       .get_frame              = s3c2410_udc_get_frame,
+       .wakeup                 = s3c2410_udc_wakeup,
+       .set_selfpowered        = s3c2410_udc_set_selfpowered,
+       .pullup                 = s3c2410_udc_pullup,
+       .vbus_session           = s3c2410_udc_vbus_session,
+       .vbus_draw              = s3c2410_vbus_draw,
+};
+
+/*------------------------- gadget driver handling---------------------------*/
+/*
+ * s3c2410_udc_disable
+ */
+static void s3c2410_udc_disable(struct s3c2410_udc *dev)
+{
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       /* Disable all interrupts */
+       udc_write(0x00, S3C2410_UDC_USB_INT_EN_REG);
+       udc_write(0x00, S3C2410_UDC_EP_INT_EN_REG);
+
+       /* Clear the interrupt registers */
+       udc_write(S3C2410_UDC_USBINT_RESET
+                               | S3C2410_UDC_USBINT_RESUME
+                               | S3C2410_UDC_USBINT_SUSPEND,
+                       S3C2410_UDC_USB_INT_REG);
+
+       udc_write(0x1F, S3C2410_UDC_EP_INT_REG);
+
+       /* Good bye, cruel world */
+       if (udc_info && udc_info->udc_command)
+               udc_info->udc_command(S3C2410_UDC_P_DISABLE);
+
+       /* Set speed to unknown */
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+}
+
+/*
+ * s3c2410_udc_reinit
+ */
+static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
+{
+       u32 i;
+
+       /* device/ep0 records init */
+       INIT_LIST_HEAD (&dev->gadget.ep_list);
+       INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
+       dev->ep0state = EP0_IDLE;
+
+       for (i = 0; i < S3C2410_ENDPOINTS; i++) {
+               struct s3c2410_ep *ep = &dev->ep[i];
+
+               if (i != 0)
+                       list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
+
+               ep->dev = dev;
+               ep->desc = NULL;
+               ep->halted = 0;
+               INIT_LIST_HEAD (&ep->queue);
+       }
+}
+
+/*
+ * s3c2410_udc_enable
+ */
+static void s3c2410_udc_enable(struct s3c2410_udc *dev)
+{
+       int i;
+
+       dprintk(DEBUG_NORMAL, "s3c2410_udc_enable called\n");
+
+       /* dev->gadget.speed = USB_SPEED_UNKNOWN; */
+       dev->gadget.speed = USB_SPEED_FULL;
+
+       /* Set MAXP for all endpoints */
+       for (i = 0; i < S3C2410_ENDPOINTS; i++) {
+               udc_write(i, S3C2410_UDC_INDEX_REG);
+               udc_write((dev->ep[i].ep.maxpacket & 0x7ff) >> 3,
+                               S3C2410_UDC_MAXP_REG);
+       }
+
+       /* Set default power state */
+       udc_write(DEFAULT_POWER_STATE, S3C2410_UDC_PWR_REG);
+
+       /* Enable reset and suspend interrupt interrupts */
+       udc_write(S3C2410_UDC_USBINT_RESET | S3C2410_UDC_USBINT_SUSPEND,
+                       S3C2410_UDC_USB_INT_EN_REG);
+
+       /* Enable ep0 interrupt */
+       udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG);
+
+       /* time to say "hello, world" */
+       if (udc_info && udc_info->udc_command)
+               udc_info->udc_command(S3C2410_UDC_P_ENABLE);
+}
+
+/*
+ *     usb_gadget_register_driver
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+       struct s3c2410_udc *udc = the_controller;
+       int             retval;
+
+       dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n",
+               driver->driver.name);
+
+       /* Sanity checks */
+       if (!udc)
+               return -ENODEV;
+
+       if (udc->driver)
+               return -EBUSY;
+
+       if (!driver->bind || !driver->setup
+                       || driver->speed != USB_SPEED_FULL) {
+               printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
+                       driver->bind, driver->setup, driver->speed);
+               return -EINVAL;
+       }
+#if defined(MODULE)
+       if (!driver->unbind) {
+               printk(KERN_ERR "Invalid driver: no unbind method\n");
+               return -EINVAL;
+       }
+#endif
+
+       /* Hook the driver */
+       udc->driver = driver;
+       udc->gadget.dev.driver = &driver->driver;
+
+       /* Bind the driver */
+       if ((retval = device_add(&udc->gadget.dev)) != 0) {
+               printk(KERN_ERR "Error in device_add() : %d\n",retval);
+               goto register_error;
+       }
+
+       dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",
+               driver->driver.name);
+
+       if ((retval = driver->bind (&udc->gadget)) != 0) {
+               device_del(&udc->gadget.dev);
+               goto register_error;
+       }
+
+       /* Enable udc */
+       s3c2410_udc_enable(udc);
+
+       return 0;
+
+register_error:
+       udc->driver = NULL;
+       udc->gadget.dev.driver = NULL;
+       return retval;
+}
+
+/*
+ *     usb_gadget_unregister_driver
+ */
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+       struct s3c2410_udc *udc = the_controller;
+
+       if (!udc)
+               return -ENODEV;
+
+       if (!driver || driver != udc->driver || !driver->unbind)
+               return -EINVAL;
+
+       dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",
+               driver->driver.name);
+
+       if (driver->disconnect)
+               driver->disconnect(&udc->gadget);
+
+       device_del(&udc->gadget.dev);
+       udc->driver = NULL;
+
+       /* Disable udc */
+       s3c2410_udc_disable(udc);
+
+       return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+static struct s3c2410_udc memory = {
+       .gadget = {
+               .ops            = &s3c2410_ops,
+               .ep0            = &memory.ep[0].ep,
+               .name           = gadget_name,
+               .dev = {
+                       .bus_id         = "gadget",
+               },
+       },
+
+       /* control endpoint */
+       .ep[0] = {
+               .num            = 0,
+               .ep = {
+                       .name           = ep0name,
+                       .ops            = &s3c2410_ep_ops,
+                       .maxpacket      = EP0_FIFO_SIZE,
+               },
+               .dev            = &memory,
+       },
+
+       /* first group of endpoints */
+       .ep[1] = {
+               .num            = 1,
+               .ep = {
+                       .name           = "ep1-bulk",
+                       .ops            = &s3c2410_ep_ops,
+                       .maxpacket      = EP_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = EP_FIFO_SIZE,
+               .bEndpointAddress = 1,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+       },
+       .ep[2] = {
+               .num            = 2,
+               .ep = {
+                       .name           = "ep2-bulk",
+                       .ops            = &s3c2410_ep_ops,
+                       .maxpacket      = EP_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = EP_FIFO_SIZE,
+               .bEndpointAddress = 2,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+       },
+       .ep[3] = {
+               .num            = 3,
+               .ep = {
+                       .name           = "ep3-bulk",
+                       .ops            = &s3c2410_ep_ops,
+                       .maxpacket      = EP_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = EP_FIFO_SIZE,
+               .bEndpointAddress = 3,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+       },
+       .ep[4] = {
+               .num            = 4,
+               .ep = {
+                       .name           = "ep4-bulk",
+                       .ops            = &s3c2410_ep_ops,
+                       .maxpacket      = EP_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = EP_FIFO_SIZE,
+               .bEndpointAddress = 4,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+       }
+
+};
+
+/*
+ *     probe - binds to the platform device
+ */
+static int s3c2410_udc_probe(struct platform_device *pdev)
+{
+       struct s3c2410_udc *udc = &memory;
+       struct device *dev = &pdev->dev;
+       int retval;
+       unsigned int irq;
+
+       dev_dbg(dev, "%s()\n", __func__);
+
+       usb_bus_clock = clk_get(NULL, "usb-bus-gadget");
+       if (IS_ERR(usb_bus_clock)) {
+               dev_err(dev, "failed to get usb bus clock source\n");
+               return PTR_ERR(usb_bus_clock);
+       }
+
+       clk_enable(usb_bus_clock);
+
+       udc_clock = clk_get(NULL, "usb-device");
+       if (IS_ERR(udc_clock)) {
+               dev_err(dev, "failed to get udc clock source\n");
+               return PTR_ERR(udc_clock);
+       }
+
+       clk_enable(udc_clock);
+
+       mdelay(10);
+
+       dev_dbg(dev, "got and enabled clocks\n");
+
+       if (strncmp(pdev->name, "s3c2440", 7) == 0) {
+               dev_info(dev, "S3C2440: increasing FIFO to 128 bytes\n");
+               memory.ep[1].fifo_size = S3C2440_EP_FIFO_SIZE;
+               memory.ep[2].fifo_size = S3C2440_EP_FIFO_SIZE;
+               memory.ep[3].fifo_size = S3C2440_EP_FIFO_SIZE;
+               memory.ep[4].fifo_size = S3C2440_EP_FIFO_SIZE;
+       }
+
+       spin_lock_init (&udc->lock);
+       udc_info = pdev->dev.platform_data;
+
+       rsrc_start = S3C2410_PA_USBDEV;
+       rsrc_len   = S3C24XX_SZ_USBDEV;
+
+       if (!request_mem_region(rsrc_start, rsrc_len, gadget_name))
+               return -EBUSY;
+
+       base_addr = ioremap(rsrc_start, rsrc_len);
+       if (!base_addr) {
+               retval = -ENOMEM;
+               goto err_mem;
+       }
+
+       device_initialize(&udc->gadget.dev);
+       udc->gadget.dev.parent = &pdev->dev;
+       udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
+
+       the_controller = udc;
+       platform_set_drvdata(pdev, udc);
+
+       s3c2410_udc_disable(udc);
+       s3c2410_udc_reinit(udc);
+
+       /* irq setup after old hardware state is cleaned up */
+       retval = request_irq(IRQ_USBD, s3c2410_udc_irq,
+                       IRQF_DISABLED, gadget_name, udc);
+
+       if (retval != 0) {
+               dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval);
+               retval = -EBUSY;
+               goto err_map;
+       }
+
+       dev_dbg(dev, "got irq %i\n", IRQ_USBD);
+
+       if (udc_info && udc_info->vbus_pin > 0) {
+               irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
+               retval = request_irq(irq, s3c2410_udc_vbus_irq,
+                               IRQF_DISABLED | IRQF_TRIGGER_RISING
+                               | IRQF_TRIGGER_FALLING,
+                               gadget_name, udc);
+
+               if (retval != 0) {
+                       dev_err(dev, "can't get vbus irq %i, err %d\n",
+                               irq, retval);
+                       retval = -EBUSY;
+                       goto err_int;
+               }
+
+               dev_dbg(dev, "got irq %i\n", irq);
+       } else {
+               udc->vbus = 1;
+       }
+
+       if (s3c2410_udc_debugfs_root) {
+               udc->regs_info = debugfs_create_file("registers", S_IRUGO,
+                               s3c2410_udc_debugfs_root,
+                               udc, &s3c2410_udc_debugfs_fops);
+               if (IS_ERR(udc->regs_info)) {
+                       dev_warn(dev, "debugfs file creation failed %ld\n",
+                                PTR_ERR(udc->regs_info));
+                       udc->regs_info = NULL;
+               }
+       }
+
+       dev_dbg(dev, "probe ok\n");
+
+       return 0;
+
+err_int:
+       free_irq(IRQ_USBD, udc);
+err_map:
+       iounmap(base_addr);
+err_mem:
+       release_mem_region(rsrc_start, rsrc_len);
+
+       return retval;
+}
+
+/*
+ *     s3c2410_udc_remove
+ */
+static int s3c2410_udc_remove(struct platform_device *pdev)
+{
+       struct s3c2410_udc *udc = platform_get_drvdata(pdev);
+       unsigned int irq;
+
+       dev_dbg(&pdev->dev, "%s()\n", __func__);
+       if (udc->driver)
+               return -EBUSY;
+
+       debugfs_remove(udc->regs_info);
+
+       if (udc_info && udc_info->vbus_pin > 0) {
+               irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
+               free_irq(irq, udc);
+       }
+
+       free_irq(IRQ_USBD, udc);
+
+       iounmap(base_addr);
+       release_mem_region(rsrc_start, rsrc_len);
+
+       platform_set_drvdata(pdev, NULL);
+
+       if (!IS_ERR(udc_clock) && udc_clock != NULL) {
+               clk_disable(udc_clock);
+               clk_put(udc_clock);
+               udc_clock = NULL;
+       }
+
+       if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) {
+               clk_disable(usb_bus_clock);
+               clk_put(usb_bus_clock);
+               usb_bus_clock = NULL;
+       }
+
+       dev_dbg(&pdev->dev, "%s: remove ok\n", __func__);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message)
+{
+       if (udc_info && udc_info->udc_command)
+               udc_info->udc_command(S3C2410_UDC_P_DISABLE);
+
+       return 0;
+}
+
+static int s3c2410_udc_resume(struct platform_device *pdev)
+{
+       if (udc_info && udc_info->udc_command)
+               udc_info->udc_command(S3C2410_UDC_P_ENABLE);
+
+       return 0;
+}
+#else
+#define s3c2410_udc_suspend    NULL
+#define s3c2410_udc_resume     NULL
+#endif
+
+static struct platform_driver udc_driver_2410 = {
+       .driver         = {
+               .name   = "s3c2410-usbgadget",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = s3c2410_udc_probe,
+       .remove         = s3c2410_udc_remove,
+       .suspend        = s3c2410_udc_suspend,
+       .resume         = s3c2410_udc_resume,
+};
+
+static struct platform_driver udc_driver_2440 = {
+       .driver         = {
+               .name   = "s3c2440-usbgadget",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = s3c2410_udc_probe,
+       .remove         = s3c2410_udc_remove,
+       .suspend        = s3c2410_udc_suspend,
+       .resume         = s3c2410_udc_resume,
+};
+
+static int __init udc_init(void)
+{
+       int retval;
+
+       dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
+
+       s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
+       if (IS_ERR(s3c2410_udc_debugfs_root)) {
+               printk(KERN_ERR "%s: debugfs dir creation failed %ld\n",
+                       gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));
+               s3c2410_udc_debugfs_root = NULL;
+       }
+
+       retval = platform_driver_register(&udc_driver_2410);
+       if (retval)
+               goto err;
+
+       retval = platform_driver_register(&udc_driver_2440);
+       if (retval)
+               goto err;
+
+       return 0;
+
+err:
+       debugfs_remove(s3c2410_udc_debugfs_root);
+       return retval;
+}
+
+static void __exit udc_exit(void)
+{
+       platform_driver_unregister(&udc_driver_2410);
+       platform_driver_unregister(&udc_driver_2440);
+       debugfs_remove(s3c2410_udc_debugfs_root);
+}
+
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+module_init(udc_init);
+module_exit(udc_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/s3c2410_udc.h
new file mode 100644 (file)
index 0000000..9e0bece
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * linux/drivers/usb/gadget/s3c2410_udc.h
+ * Samsung on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
+ *     Additional cleanups by Ben Dooks <ben-linux@fluff.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _S3C2410_UDC_H
+#define _S3C2410_UDC_H
+
+struct s3c2410_ep {
+       struct list_head                queue;
+       unsigned long                   last_io;        /* jiffies timestamp */
+       struct usb_gadget               *gadget;
+       struct s3c2410_udc              *dev;
+       const struct usb_endpoint_descriptor *desc;
+       struct usb_ep                   ep;
+       u8                              num;
+
+       unsigned short                  fifo_size;
+       u8                              bEndpointAddress;
+       u8                              bmAttributes;
+
+       unsigned                        halted : 1;
+       unsigned                        already_seen : 1;
+       unsigned                        setup_stage : 1;
+};
+
+
+/* Warning : ep0 has a fifo of 16 bytes */
+/* Don't try to set 32 or 64            */
+/* also testusb 14 fails  wit 16 but is */
+/* fine with 8                          */
+#define EP0_FIFO_SIZE           8
+#define EP_FIFO_SIZE           64
+#define DEFAULT_POWER_STATE    0x00
+
+#define S3C2440_EP_FIFO_SIZE   128
+
+static const char ep0name [] = "ep0";
+
+static const char *const ep_name[] = {
+       ep0name,                                /* everyone has ep0 */
+       /* s3c2410 four bidirectional bulk endpoints */
+       "ep1-bulk", "ep2-bulk", "ep3-bulk", "ep4-bulk",
+};
+
+#define S3C2410_ENDPOINTS       ARRAY_SIZE(ep_name)
+
+struct s3c2410_request {
+       struct list_head                queue;          /* ep's requests */
+       struct usb_request              req;
+};
+
+enum ep0_state {
+        EP0_IDLE,
+        EP0_IN_DATA_PHASE,
+        EP0_OUT_DATA_PHASE,
+        EP0_END_XFER,
+        EP0_STALL,
+};
+
+static const char *ep0states[]= {
+        "EP0_IDLE",
+        "EP0_IN_DATA_PHASE",
+        "EP0_OUT_DATA_PHASE",
+        "EP0_END_XFER",
+        "EP0_STALL",
+};
+
+struct s3c2410_udc {
+       spinlock_t                      lock;
+
+       struct s3c2410_ep               ep[S3C2410_ENDPOINTS];
+       int                             address;
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+       struct s3c2410_request          fifo_req;
+       u8                              fifo_buf[EP_FIFO_SIZE];
+       u16                             devstatus;
+
+       u32                             port_status;
+       int                             ep0state;
+
+       unsigned                        got_irq : 1;
+
+       unsigned                        req_std : 1;
+       unsigned                        req_config : 1;
+       unsigned                        req_pending : 1;
+       u8                              vbus;
+       struct dentry                   *regs_info;
+};
+
+#endif
index f847c3414be31ac372d42e91ed20451675b6dab1..dd33ff0ae4cecb6984b5ac503c7567d7260857fc 100644 (file)
@@ -2215,7 +2215,7 @@ static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
  *
  * Free the buffer and all associated memory.
  */
-void gs_buf_free(struct gs_buf *gb)
+static void gs_buf_free(struct gs_buf *gb)
 {
        if (gb) {
                kfree(gb->buf_buf);
@@ -2228,7 +2228,7 @@ void gs_buf_free(struct gs_buf *gb)
  *
  * Clear out all data in the circular buffer.
  */
-void gs_buf_clear(struct gs_buf *gb)
+static void gs_buf_clear(struct gs_buf *gb)
 {
        if (gb != NULL)
                gb->buf_get = gb->buf_put;
@@ -2241,7 +2241,7 @@ void gs_buf_clear(struct gs_buf *gb)
  * Return the number of bytes of data available in the circular
  * buffer.
  */
-unsigned int gs_buf_data_avail(struct gs_buf *gb)
+static unsigned int gs_buf_data_avail(struct gs_buf *gb)
 {
        if (gb != NULL)
                return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
@@ -2255,7 +2255,7 @@ unsigned int gs_buf_data_avail(struct gs_buf *gb)
  * Return the number of bytes of space available in the circular
  * buffer.
  */
-unsigned int gs_buf_space_avail(struct gs_buf *gb)
+static unsigned int gs_buf_space_avail(struct gs_buf *gb)
 {
        if (gb != NULL)
                return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
@@ -2271,7 +2271,8 @@ unsigned int gs_buf_space_avail(struct gs_buf *gb)
  *
  * Return the number of bytes copied.
  */
-unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
+static unsigned int
+gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
 {
        unsigned int len;
 
@@ -2309,7 +2310,8 @@ unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
  *
  * Return the number of bytes copied.
  */
-unsigned int gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
+static unsigned int
+gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
 {
        unsigned int len;
 
index 7078374d0b79d0ba36b5b6b297a05e412bf4302b..a2e6e3fc8c8d731b516ec3880ea3a987f3098438 100644 (file)
@@ -481,8 +481,7 @@ alloc_ep_req (struct usb_ep *ep, unsigned length)
        req = usb_ep_alloc_request (ep, GFP_ATOMIC);
        if (req) {
                req->length = length;
-               req->buf = usb_ep_alloc_buffer (ep, length,
-                               &req->dma, GFP_ATOMIC);
+               req->buf = kmalloc(length, GFP_ATOMIC);
                if (!req->buf) {
                        usb_ep_free_request (ep, req);
                        req = NULL;
@@ -493,8 +492,7 @@ alloc_ep_req (struct usb_ep *ep, unsigned length)
 
 static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
 {
-       if (req->buf)
-               usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
+       kfree(req->buf);
        usb_ep_free_request (ep, req);
 }
 
@@ -1199,8 +1197,7 @@ autoconf_fail:
        dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
        if (!dev->req)
                goto enomem;
-       dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
-                               &dev->req->dma, GFP_KERNEL);
+       dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
        if (!dev->req->buf)
                goto enomem;
 
index 62711870f8ee1fd5dbb8d974ad3b2a74466c7ea5..2f529828c74d23232a0d060b8d00108e6834ccea 100644 (file)
@@ -69,8 +69,20 @@ config USB_EHCI_TT_NEWSCHED
 
 config USB_EHCI_BIG_ENDIAN_MMIO
        bool
-       depends on USB_EHCI_HCD
-       default n
+       depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX)
+       default y
+
+config USB_EHCI_BIG_ENDIAN_DESC
+       bool
+       depends on USB_EHCI_HCD && 440EPX
+       default y
+
+config USB_EHCI_FSL
+       bool
+       select USB_EHCI_ROOT_HUB_TT
+       default y if MPC834x || PPC_MPC831x
+       ---help---
+         Variation of ARC USB block used in some Freescale chips.
 
 config USB_ISP116X_HCD
        tristate "ISP116X HCD support"
@@ -224,3 +236,15 @@ config USB_SL811_CS
          To compile this driver as a module, choose M here: the
          module will be called "sl811_cs".
 
+config USB_R8A66597_HCD
+       tristate "R8A66597 HCD suppoort"
+       depends on USB
+       help
+         The R8A66597 is a USB 2.0 host and peripheral controller.
+
+         Enable this option if your board has this chip, and you want
+         to use it as a host controller.  If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called r8a66597-hcd.
+
index 2ff396bd180fe514fab9c83395e773db066b8209..bb8e9d44f371243c91097cae75ac3c5b931a757d 100644 (file)
@@ -15,3 +15,5 @@ obj-$(CONFIG_USB_UHCI_HCD)    += uhci-hcd.o
 obj-$(CONFIG_USB_SL811_HCD)    += sl811-hcd.o
 obj-$(CONFIG_USB_SL811_CS)     += sl811_cs.o
 obj-$(CONFIG_USB_U132_HCD)     += u132-hcd.o
+obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
+
index 43eddaecc3dd520da48e9dcb7367157d8f7ff565..c9cc4413198e15d977a5d1e8b4d671eb2d72188a 100644 (file)
@@ -52,7 +52,7 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
                HCS_INDICATOR (params) ? " ind" : "",
                HCS_N_CC (params),
                HCS_N_PCC (params),
-               HCS_PORTROUTED (params) ? "" : " ordered",
+               HCS_PORTROUTED (params) ? "" : " ordered",
                HCS_PPC (params) ? "" : " !ppc",
                HCS_N_PORTS (params)
                );
@@ -91,20 +91,20 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label)
 
        if (HCC_ISOC_CACHE (params)) {
                ehci_dbg (ehci,
-                    "%s hcc_params %04x caching frame %s%s%s\n",
-                    label, params,
-                    HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
-                    HCC_CANPARK (params) ? " park" : "",
-                    HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
+                       "%s hcc_params %04x caching frame %s%s%s\n",
+                       label, params,
+                       HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
+                       HCC_CANPARK(params) ? " park" : "",
+                       HCC_64BIT_ADDR(params) ? " 64 bit addr" : "");
        } else {
                ehci_dbg (ehci,
-                    "%s hcc_params %04x thresh %d uframes %s%s%s\n",
-                    label,
-                    params,
-                    HCC_ISOC_THRES (params),
-                    HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
-                    HCC_CANPARK (params) ? " park" : "",
-                    HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
+                       "%s hcc_params %04x thresh %d uframes %s%s%s\n",
+                       label,
+                       params,
+                       HCC_ISOC_THRES(params),
+                       HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
+                       HCC_CANPARK(params) ? " park" : "",
+                       HCC_64BIT_ADDR(params) ? " 64 bit addr" : "");
        }
 }
 #else
@@ -115,23 +115,23 @@ static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {}
 
 #ifdef DEBUG
 
-static void __attribute__((__unused__))
+static void __maybe_unused
 dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd)
 {
-       ehci_dbg (ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
-               le32_to_cpup (&qtd->hw_next),
-               le32_to_cpup (&qtd->hw_alt_next),
-               le32_to_cpup (&qtd->hw_token),
-               le32_to_cpup (&qtd->hw_buf [0]));
+       ehci_dbg(ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
+               hc32_to_cpup(ehci, &qtd->hw_next),
+               hc32_to_cpup(ehci, &qtd->hw_alt_next),
+               hc32_to_cpup(ehci, &qtd->hw_token),
+               hc32_to_cpup(ehci, &qtd->hw_buf [0]));
        if (qtd->hw_buf [1])
-               ehci_dbg (ehci, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
-                       le32_to_cpup (&qtd->hw_buf [1]),
-                       le32_to_cpup (&qtd->hw_buf [2]),
-                       le32_to_cpup (&qtd->hw_buf [3]),
-                       le32_to_cpup (&qtd->hw_buf [4]));
+               ehci_dbg(ehci, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
+                       hc32_to_cpup(ehci, &qtd->hw_buf[1]),
+                       hc32_to_cpup(ehci, &qtd->hw_buf[2]),
+                       hc32_to_cpup(ehci, &qtd->hw_buf[3]),
+                       hc32_to_cpup(ehci, &qtd->hw_buf[4]));
 }
 
-static void __attribute__((__unused__))
+static void __maybe_unused
 dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
        ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label,
@@ -140,51 +140,53 @@ dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
        dbg_qtd ("overlay", ehci, (struct ehci_qtd *) &qh->hw_qtd_next);
 }
 
-static void __attribute__((__unused__))
+static void __maybe_unused
 dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
 {
        ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n",
-               label, itd->frame, itd, le32_to_cpu(itd->hw_next), itd->urb);
+               label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next),
+               itd->urb);
        ehci_dbg (ehci,
                "  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-               le32_to_cpu(itd->hw_transaction[0]),
-               le32_to_cpu(itd->hw_transaction[1]),
-               le32_to_cpu(itd->hw_transaction[2]),
-               le32_to_cpu(itd->hw_transaction[3]),
-               le32_to_cpu(itd->hw_transaction[4]),
-               le32_to_cpu(itd->hw_transaction[5]),
-               le32_to_cpu(itd->hw_transaction[6]),
-               le32_to_cpu(itd->hw_transaction[7]));
+               hc32_to_cpu(ehci, itd->hw_transaction[0]),
+               hc32_to_cpu(ehci, itd->hw_transaction[1]),
+               hc32_to_cpu(ehci, itd->hw_transaction[2]),
+               hc32_to_cpu(ehci, itd->hw_transaction[3]),
+               hc32_to_cpu(ehci, itd->hw_transaction[4]),
+               hc32_to_cpu(ehci, itd->hw_transaction[5]),
+               hc32_to_cpu(ehci, itd->hw_transaction[6]),
+               hc32_to_cpu(ehci, itd->hw_transaction[7]));
        ehci_dbg (ehci,
                "  buf:   %08x %08x %08x %08x %08x %08x %08x\n",
-               le32_to_cpu(itd->hw_bufp[0]),
-               le32_to_cpu(itd->hw_bufp[1]),
-               le32_to_cpu(itd->hw_bufp[2]),
-               le32_to_cpu(itd->hw_bufp[3]),
-               le32_to_cpu(itd->hw_bufp[4]),
-               le32_to_cpu(itd->hw_bufp[5]),
-               le32_to_cpu(itd->hw_bufp[6]));
+               hc32_to_cpu(ehci, itd->hw_bufp[0]),
+               hc32_to_cpu(ehci, itd->hw_bufp[1]),
+               hc32_to_cpu(ehci, itd->hw_bufp[2]),
+               hc32_to_cpu(ehci, itd->hw_bufp[3]),
+               hc32_to_cpu(ehci, itd->hw_bufp[4]),
+               hc32_to_cpu(ehci, itd->hw_bufp[5]),
+               hc32_to_cpu(ehci, itd->hw_bufp[6]));
        ehci_dbg (ehci, "  index: %d %d %d %d %d %d %d %d\n",
                itd->index[0], itd->index[1], itd->index[2],
                itd->index[3], itd->index[4], itd->index[5],
                itd->index[6], itd->index[7]);
 }
 
-static void __attribute__((__unused__))
+static void __maybe_unused
 dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd)
 {
        ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n",
-               label, sitd->frame, sitd, le32_to_cpu(sitd->hw_next), sitd->urb);
+               label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next),
+               sitd->urb);
        ehci_dbg (ehci,
                "  addr %08x sched %04x result %08x buf %08x %08x\n",
-               le32_to_cpu(sitd->hw_fullspeed_ep),
-               le32_to_cpu(sitd->hw_uframe),
-               le32_to_cpu(sitd->hw_results),
-               le32_to_cpu(sitd->hw_buf [0]),
-               le32_to_cpu(sitd->hw_buf [1]));
+               hc32_to_cpu(ehci, sitd->hw_fullspeed_ep),
+               hc32_to_cpu(ehci, sitd->hw_uframe),
+               hc32_to_cpu(ehci, sitd->hw_results),
+               hc32_to_cpu(ehci, sitd->hw_buf[0]),
+               hc32_to_cpu(ehci, sitd->hw_buf[1]));
 }
 
-static int __attribute__((__unused__))
+static int __maybe_unused
 dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
 {
        return scnprintf (buf, len,
@@ -203,7 +205,7 @@ dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
                );
 }
 
-static int __attribute__((__unused__))
+static int __maybe_unused
 dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
 {
        return scnprintf (buf, len,
@@ -267,28 +269,27 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status)
                (status & PORT_PEC) ? " PEC" : "",
                (status & PORT_PE) ? " PE" : "",
                (status & PORT_CSC) ? " CSC" : "",
-               (status & PORT_CONNECT) ? " CONNECT" : ""
-           );
+               (status & PORT_CONNECT) ? " CONNECT" : "");
 }
 
 #else
-static inline void __attribute__((__unused__))
+static inline void __maybe_unused
 dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
 {}
 
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
 dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
 { return 0; }
 
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
 dbg_command_buf (char *buf, unsigned len, const char *label, u32 command)
 { return 0; }
 
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
 dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
 { return 0; }
 
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
 dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status)
 { return 0; }
 
@@ -332,9 +333,10 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
                default: tmp = '?'; break; \
                }; tmp; })
 
-static inline char token_mark (__le32 token)
+static inline char token_mark(struct ehci_hcd *ehci, __hc32 token)
 {
-       __u32 v = le32_to_cpu (token);
+       __u32 v = hc32_to_cpu(ehci, token);
+
        if (v & QTD_STS_ACTIVE)
                return '*';
        if (v & QTD_STS_HALT)
@@ -360,46 +362,48 @@ static void qh_lines (
        unsigned                size = *sizep;
        char                    *next = *nextp;
        char                    mark;
+       u32                     list_end = EHCI_LIST_END(ehci);
 
-       if (qh->hw_qtd_next == EHCI_LIST_END)   /* NEC does this */
+       if (qh->hw_qtd_next == list_end)        /* NEC does this */
                mark = '@';
        else
-               mark = token_mark (qh->hw_token);
+               mark = token_mark(ehci, qh->hw_token);
        if (mark == '/') {      /* qh_alt_next controls qh advance? */
-               if ((qh->hw_alt_next & QTD_MASK) == ehci->async->hw_alt_next)
+               if ((qh->hw_alt_next & QTD_MASK(ehci))
+                               == ehci->async->hw_alt_next)
                        mark = '#';     /* blocked */
-               else if (qh->hw_alt_next == EHCI_LIST_END)
+               else if (qh->hw_alt_next == list_end)
                        mark = '.';     /* use hw_qtd_next */
                /* else alt_next points to some other qtd */
        }
-       scratch = le32_to_cpup (&qh->hw_info1);
-       hw_curr = (mark == '*') ? le32_to_cpup (&qh->hw_current) : 0;
+       scratch = hc32_to_cpup(ehci, &qh->hw_info1);
+       hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &qh->hw_current) : 0;
        temp = scnprintf (next, size,
                        "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
                        qh, scratch & 0x007f,
                        speed_char (scratch),
                        (scratch >> 8) & 0x000f,
-                       scratch, le32_to_cpup (&qh->hw_info2),
-                       le32_to_cpup (&qh->hw_token), mark,
-                       (__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token)
+                       scratch, hc32_to_cpup(ehci, &qh->hw_info2),
+                       hc32_to_cpup(ehci, &qh->hw_token), mark,
+                       (cpu_to_hc32(ehci, QTD_TOGGLE) & qh->hw_token)
                                ? "data1" : "data0",
-                       (le32_to_cpup (&qh->hw_alt_next) >> 1) & 0x0f);
+                       (hc32_to_cpup(ehci, &qh->hw_alt_next) >> 1) & 0x0f);
        size -= temp;
        next += temp;
 
        /* hc may be modifying the list as we read it ... */
        list_for_each (entry, &qh->qtd_list) {
                td = list_entry (entry, struct ehci_qtd, qtd_list);
-               scratch = le32_to_cpup (&td->hw_token);
+               scratch = hc32_to_cpup(ehci, &td->hw_token);
                mark = ' ';
                if (hw_curr == td->qtd_dma)
                        mark = '*';
-               else if (qh->hw_qtd_next == cpu_to_le32(td->qtd_dma))
+               else if (qh->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma))
                        mark = '+';
                else if (QTD_LENGTH (scratch)) {
                        if (td->hw_alt_next == ehci->async->hw_alt_next)
                                mark = '#';
-                       else if (td->hw_alt_next != EHCI_LIST_END)
+                       else if (td->hw_alt_next != list_end)
                                mark = '/';
                }
                temp = snprintf (next, size,
@@ -490,7 +494,7 @@ show_periodic (struct class_device *class_dev, char *buf)
        unsigned                temp, size, seen_count;
        char                    *next;
        unsigned                i;
-       __le32                  tag;
+       __hc32                  tag;
 
        if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC)))
                return 0;
@@ -514,18 +518,19 @@ show_periodic (struct class_device *class_dev, char *buf)
                p = ehci->pshadow [i];
                if (likely (!p.ptr))
                        continue;
-               tag = Q_NEXT_TYPE (ehci->periodic [i]);
+               tag = Q_NEXT_TYPE(ehci, ehci->periodic [i]);
 
                temp = scnprintf (next, size, "%4d: ", i);
                size -= temp;
                next += temp;
 
                do {
-                       switch (tag) {
+                       switch (hc32_to_cpu(ehci, tag)) {
                        case Q_TYPE_QH:
                                temp = scnprintf (next, size, " qh%d-%04x/%p",
                                                p.qh->period,
-                                               le32_to_cpup (&p.qh->hw_info2)
+                                               hc32_to_cpup(ehci,
+                                                               &p.qh->hw_info2)
                                                        /* uframe masks */
                                                        & (QH_CMASK | QH_SMASK),
                                                p.qh);
@@ -543,7 +548,7 @@ show_periodic (struct class_device *class_dev, char *buf)
                                }
                                /* show more info the first time around */
                                if (temp == seen_count && p.ptr) {
-                                       u32     scratch = le32_to_cpup (
+                                       u32     scratch = hc32_to_cpup(ehci,
                                                        &p.qh->hw_info1);
                                        struct ehci_qtd *qtd;
                                        char            *type = "";
@@ -554,7 +559,8 @@ show_periodic (struct class_device *class_dev, char *buf)
                                                        &p.qh->qtd_list,
                                                        qtd_list) {
                                                temp++;
-                                               switch (0x03 & (le32_to_cpu (
+                                               switch (0x03 & (hc32_to_cpu(
+                                                       ehci,
                                                        qtd->hw_token) >> 8)) {
                                                case 0: type = "out"; continue;
                                                case 1: type = "in"; continue;
@@ -576,7 +582,7 @@ show_periodic (struct class_device *class_dev, char *buf)
                                } else
                                        temp = 0;
                                if (p.qh) {
-                                       tag = Q_NEXT_TYPE (p.qh->hw_next);
+                                       tag = Q_NEXT_TYPE(ehci, p.qh->hw_next);
                                        p = p.qh->qh_next;
                                }
                                break;
@@ -584,23 +590,23 @@ show_periodic (struct class_device *class_dev, char *buf)
                                temp = scnprintf (next, size,
                                        " fstn-%8x/%p", p.fstn->hw_prev,
                                        p.fstn);
-                               tag = Q_NEXT_TYPE (p.fstn->hw_next);
+                               tag = Q_NEXT_TYPE(ehci, p.fstn->hw_next);
                                p = p.fstn->fstn_next;
                                break;
                        case Q_TYPE_ITD:
                                temp = scnprintf (next, size,
                                        " itd/%p", p.itd);
-                               tag = Q_NEXT_TYPE (p.itd->hw_next);
+                               tag = Q_NEXT_TYPE(ehci, p.itd->hw_next);
                                p = p.itd->itd_next;
                                break;
                        case Q_TYPE_SITD:
                                temp = scnprintf (next, size,
                                        " sitd%d-%04x/%p",
                                        p.sitd->stream->interval,
-                                       le32_to_cpup (&p.sitd->hw_uframe)
+                                       hc32_to_cpup(ehci, &p.sitd->hw_uframe)
                                                & 0x0000ffff,
                                        p.sitd);
-                               tag = Q_NEXT_TYPE (p.sitd->hw_next);
+                               tag = Q_NEXT_TYPE(ehci, p.sitd->hw_next);
                                p = p.sitd->sitd_next;
                                break;
                        }
@@ -673,7 +679,8 @@ show_registers (struct class_device *class_dev, char *buf)
                unsigned        count = 256/4;
 
                pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
-               offset = HCC_EXT_CAPS (ehci_readl(ehci, &ehci->caps->hcc_params));
+               offset = HCC_EXT_CAPS(ehci_readl(ehci,
+                               &ehci->caps->hcc_params));
                while (offset && count--) {
                        pci_read_config_dword (pdev, offset, &cap);
                        switch (cap & 0xff) {
@@ -740,14 +747,16 @@ show_registers (struct class_device *class_dev, char *buf)
 
        for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) {
                temp = dbg_port_buf (scratch, sizeof scratch, label, i,
-                               ehci_readl(ehci, &ehci->regs->port_status [i - 1]));
+                               ehci_readl(ehci,
+                                       &ehci->regs->port_status[i - 1]));
                temp = scnprintf (next, size, fmt, temp, scratch);
                size -= temp;
                next += temp;
                if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) {
                        temp = scnprintf (next, size,
                                        "    debug control %08x\n",
-                                       ehci_readl(ehci, &ehci->debug->control));
+                                       ehci_readl(ehci,
+                                               &ehci->debug->control));
                        size -= temp;
                        next += temp;
                }
index c7a7c590426fd2d54812a46f45a6a495a22b0ca2..b7b7bfbce527e057c7f509d0260b98609a7eeca5 100644 (file)
@@ -67,7 +67,8 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
         * in host mode.
         */
        if (!((pdata->operating_mode == FSL_USB2_DR_HOST) ||
-             (pdata->operating_mode == FSL_USB2_MPH_HOST))) {
+             (pdata->operating_mode == FSL_USB2_MPH_HOST) ||
+             (pdata->operating_mode == FSL_USB2_DR_OTG))) {
                dev_err(&pdev->dev,
                        "Non Host Mode configured for %s. Wrong driver linked.\n",
                        pdev->dev.bus_id);
@@ -185,12 +186,14 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        struct fsl_usb2_platform_data *pdata;
        void __iomem *non_ehci = hcd->regs;
+       u32 temp;
 
        pdata =
            (struct fsl_usb2_platform_data *)hcd->self.controller->
            platform_data;
        /* Enable PHY interface in the control reg. */
-       out_be32(non_ehci + FSL_SOC_USB_CTRL, 0x00000004);
+       temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+       out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
        out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
 
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
@@ -206,7 +209,8 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
        out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
 #endif
 
-       if (pdata->operating_mode == FSL_USB2_DR_HOST)
+       if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
+                       (pdata->operating_mode == FSL_USB2_DR_OTG))
                mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
 
        if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
index 099aff64f5361de4cb87c25bb37e8f45d3afbd98..c4e15ed1405a96eaa85003ae796ba316b37f9714 100644 (file)
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
-#ifdef CONFIG_PPC_PS3
-#include <asm/firmware.h>
-#endif
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -201,9 +197,15 @@ static void tdi_reset (struct ehci_hcd *ehci)
        u32 __iomem     *reg_ptr;
        u32             tmp;
 
-       reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68);
+       reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
        tmp = ehci_readl(ehci, reg_ptr);
-       tmp |= 0x3;
+       tmp |= USBMODE_CM_HC;
+       /* The default byte access to MMR space is LE after
+        * controller reset. Set the required endian mode
+        * for transfer buffers to match the host microprocessor
+        */
+       if (ehci_big_endian_mmio(ehci))
+               tmp |= USBMODE_BE;
        ehci_writel(ehci, tmp, reg_ptr);
 }
 
@@ -273,6 +275,58 @@ static void ehci_work(struct ehci_hcd *ehci);
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_CPU_FREQ
+
+#include <linux/cpufreq.h>
+
+static void ehci_cpufreq_pause (struct ehci_hcd *ehci)
+{
+       unsigned long   flags;
+
+       spin_lock_irqsave(&ehci->lock, flags);
+       if (!ehci->cpufreq_changing++)
+               qh_inactivate_split_intr_qhs(ehci);
+       spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+static void ehci_cpufreq_unpause (struct ehci_hcd *ehci)
+{
+       unsigned long   flags;
+
+       spin_lock_irqsave(&ehci->lock, flags);
+       if (!--ehci->cpufreq_changing)
+               qh_reactivate_split_intr_qhs(ehci);
+       spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+/*
+ * ehci_cpufreq_notifier is needed to avoid MMF errors that occur when
+ * EHCI controllers that don't cache many uframes get delayed trying to
+ * read main memory during CPU frequency transitions.  This can cause
+ * split interrupt transactions to not be completed in the required uframe.
+ * This has been observed on the Broadcom/ServerWorks HT1000 controller.
+ */
+static int ehci_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+                                void *data)
+{
+       struct ehci_hcd *ehci = container_of(nb, struct ehci_hcd,
+                                            cpufreq_transition);
+
+       switch (val) {
+       case CPUFREQ_PRECHANGE:
+               ehci_cpufreq_pause(ehci);
+               break;
+       case CPUFREQ_POSTCHANGE:
+               ehci_cpufreq_unpause(ehci);
+               break;
+       }
+       return 0;
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 static void ehci_watchdog (unsigned long param)
 {
        struct ehci_hcd         *ehci = (struct ehci_hcd *) param;
@@ -347,6 +401,8 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
                                is_on ? SetPortFeature : ClearPortFeature,
                                USB_PORT_FEAT_POWER,
                                port--, NULL, 0);
+       /* Flush those writes */
+       ehci_readl(ehci, &ehci->regs->command);
        msleep(20);
 }
 
@@ -404,6 +460,10 @@ static void ehci_stop (struct usb_hcd *hcd)
        ehci_writel(ehci, 0, &ehci->regs->intr_enable);
        spin_unlock_irq(&ehci->lock);
 
+#ifdef CONFIG_CPU_FREQ
+       cpufreq_unregister_notifier(&ehci->cpufreq_transition,
+                                   CPUFREQ_TRANSITION_NOTIFIER);
+#endif
        /* let companion controllers work when we aren't */
        ehci_writel(ehci, 0, &ehci->regs->configured_flag);
 
@@ -470,12 +530,12 @@ static int ehci_init(struct usb_hcd *hcd)
         * from automatically advancing to the next td after short reads.
         */
        ehci->async->qh_next.qh = NULL;
-       ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma);
-       ehci->async->hw_info1 = cpu_to_le32(QH_HEAD);
-       ehci->async->hw_token = cpu_to_le32(QTD_STS_HALT);
-       ehci->async->hw_qtd_next = EHCI_LIST_END;
+       ehci->async->hw_next = QH_NEXT(ehci, ehci->async->qh_dma);
+       ehci->async->hw_info1 = cpu_to_hc32(ehci, QH_HEAD);
+       ehci->async->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
+       ehci->async->hw_qtd_next = EHCI_LIST_END(ehci);
        ehci->async->qh_state = QH_STATE_LINKED;
-       ehci->async->hw_alt_next = QTD_NEXT(ehci->async->dummy->qtd_dma);
+       ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma);
 
        /* clear interrupt enables, set irq latency */
        if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
@@ -509,6 +569,17 @@ static int ehci_init(struct usb_hcd *hcd)
        }
        ehci->command = temp;
 
+#ifdef CONFIG_CPU_FREQ
+       INIT_LIST_HEAD(&ehci->split_intr_qhs);
+       /*
+        * If the EHCI controller caches enough uframes, this probably
+        * isn't needed unless there are so many low/full speed devices
+        * that the controller's can't cache it all.
+        */
+       ehci->cpufreq_transition.notifier_call = ehci_cpufreq_notifier;
+       cpufreq_register_notifier(&ehci->cpufreq_transition,
+                                 CPUFREQ_TRANSITION_NOTIFIER);
+#endif
        return 0;
 }
 
@@ -925,7 +996,7 @@ MODULE_LICENSE ("GPL");
 #define        PCI_DRIVER              ehci_pci_driver
 #endif
 
-#ifdef CONFIG_MPC834x
+#ifdef CONFIG_USB_EHCI_FSL
 #include "ehci-fsl.c"
 #define        PLATFORM_DRIVER         ehci_fsl_driver
 #endif
@@ -937,7 +1008,12 @@ MODULE_LICENSE ("GPL");
 
 #ifdef CONFIG_PPC_PS3
 #include "ehci-ps3.c"
-#define        PS3_SYSTEM_BUS_DRIVER   ps3_ehci_sb_driver
+#define        PS3_SYSTEM_BUS_DRIVER   ps3_ehci_driver
+#endif
+
+#ifdef CONFIG_440EPX
+#include "ehci-ppc-soc.c"
+#define        PLATFORM_DRIVER         ehci_ppc_soc_driver
 #endif
 
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
@@ -971,18 +1047,15 @@ static int __init ehci_hcd_init(void)
 #endif
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-       if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
-               retval = ps3_system_bus_driver_register(
-                               &PS3_SYSTEM_BUS_DRIVER);
-               if (retval < 0) {
+       retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
+       if (retval < 0) {
 #ifdef PLATFORM_DRIVER
-                       platform_driver_unregister(&PLATFORM_DRIVER);
+               platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PCI_DRIVER
-                       pci_unregister_driver(&PCI_DRIVER);
+               pci_unregister_driver(&PCI_DRIVER);
 #endif
-                       return retval;
-               }
+               return retval;
        }
 #endif
 
@@ -999,8 +1072,7 @@ static void __exit ehci_hcd_cleanup(void)
        pci_unregister_driver(&PCI_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-       if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-               ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+       ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ehci_hcd_cleanup);
index f4d301bc83b9c8bf82d6a434fa2833f6aa3b1b13..0dcb4164dc8368a9187b670c2a303c39cfdfa109 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_USB_PERSIST
+
+static int ehci_hub_control(
+       struct usb_hcd  *hcd,
+       u16             typeReq,
+       u16             wValue,
+       u16             wIndex,
+       char            *buf,
+       u16             wLength
+);
+
+/* After a power loss, ports that were owned by the companion must be
+ * reset so that the companion can still own them.
+ */
+static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+{
+       u32 __iomem     *reg;
+       u32             status;
+       int             port;
+       __le32          buf;
+       struct usb_hcd  *hcd = ehci_to_hcd(ehci);
+
+       if (!ehci->owned_ports)
+               return;
+
+       /* Give the connections some time to appear */
+       msleep(20);
+
+       port = HCS_N_PORTS(ehci->hcs_params);
+       while (port--) {
+               if (test_bit(port, &ehci->owned_ports)) {
+                       reg = &ehci->regs->port_status[port];
+                       status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+
+                       /* Port already owned by companion? */
+                       if (status & PORT_OWNER)
+                               clear_bit(port, &ehci->owned_ports);
+                       else if (test_bit(port, &ehci->companion_ports))
+                               ehci_writel(ehci, status & ~PORT_PE, reg);
+                       else
+                               ehci_hub_control(hcd, SetPortFeature,
+                                               USB_PORT_FEAT_RESET, port + 1,
+                                               NULL, 0);
+               }
+       }
+
+       if (!ehci->owned_ports)
+               return;
+       msleep(90);             /* Wait for resets to complete */
+
+       port = HCS_N_PORTS(ehci->hcs_params);
+       while (port--) {
+               if (test_bit(port, &ehci->owned_ports)) {
+                       ehci_hub_control(hcd, GetPortStatus,
+                                       0, port + 1,
+                                       (char *) &buf, sizeof(buf));
+
+                       /* The companion should now own the port,
+                        * but if something went wrong the port must not
+                        * remain enabled.
+                        */
+                       reg = &ehci->regs->port_status[port];
+                       status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+                       if (status & PORT_OWNER)
+                               ehci_writel(ehci, status | PORT_CSC, reg);
+                       else {
+                               ehci_dbg(ehci, "failed handover port %d: %x\n",
+                                               port + 1, status);
+                               ehci_writel(ehci, status & ~PORT_PE, reg);
+                       }
+               }
+       }
+
+       ehci->owned_ports = 0;
+}
+
+#else  /* CONFIG_USB_PERSIST */
+
+static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+{ }
+
+#endif
+
 #ifdef CONFIG_PM
 
 static int ehci_bus_suspend (struct usb_hcd *hcd)
@@ -60,14 +143,16 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
         * then manually resume them in the bus_resume() routine.
         */
        ehci->bus_suspended = 0;
+       ehci->owned_ports = 0;
        while (port--) {
                u32 __iomem     *reg = &ehci->regs->port_status [port];
                u32             t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
                u32             t2 = t1;
 
                /* keep track of which ports we suspend */
-               if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) &&
-                               !(t1 & PORT_SUSPEND)) {
+               if (t1 & PORT_OWNER)
+                       set_bit(port, &ehci->owned_ports);
+               else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) {
                        t2 |= PORT_SUSPEND;
                        set_bit(port, &ehci->bus_suspended);
                }
@@ -108,11 +193,16 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
        u32                     temp;
+       u32                     power_okay;
        int                     i;
 
        if (time_before (jiffies, ehci->next_statechange))
                msleep(5);
        spin_lock_irq (&ehci->lock);
+       if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+               spin_unlock_irq(&ehci->lock);
+               return -ESHUTDOWN;
+       }
 
        /* Ideally and we've got a real resume here, and no port's power
         * was lost.  (For PCI, that means Vaux was maintained.)  But we
@@ -120,8 +210,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
         * the last user of the controller, not reset/pm hardware keeping
         * state we gave to it.
         */
-       temp = ehci_readl(ehci, &ehci->regs->intr_enable);
-       ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");
+       power_okay = ehci_readl(ehci, &ehci->regs->intr_enable);
+       ehci_dbg(ehci, "resume root hub%s\n",
+                       power_okay ? "" : " after power loss");
 
        /* at least some APM implementations will try to deliver
         * IRQs right away, so delay them until we're ready.
@@ -184,6 +275,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
        ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
 
        spin_unlock_irq (&ehci->lock);
+
+       if (!power_okay)
+               ehci_handover_companion_ports(ehci);
        return 0;
 }
 
@@ -448,7 +542,8 @@ static int ehci_hub_control (
 ) {
        struct ehci_hcd *ehci = hcd_to_ehci (hcd);
        int             ports = HCS_N_PORTS (ehci->hcs_params);
-       u32 __iomem     *status_reg = &ehci->regs->port_status[wIndex - 1];
+       u32 __iomem     *status_reg = &ehci->regs->port_status[
+                               (wIndex & 0xff) - 1];
        u32             temp, status;
        unsigned long   flags;
        int             retval = 0;
@@ -556,9 +651,24 @@ static int ehci_hub_control (
                        status |= 1 << USB_PORT_FEAT_C_CONNECTION;
                if (temp & PORT_PEC)
                        status |= 1 << USB_PORT_FEAT_C_ENABLE;
-               if ((temp & PORT_OCC) && !ignore_oc)
+
+               if ((temp & PORT_OCC) && !ignore_oc){
                        status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
 
+                       /*
+                        * Hubs should disable port power on over-current.
+                        * However, not all EHCI implementations do this
+                        * automatically, even if they _do_ support per-port
+                        * power switching; they're allowed to just limit the
+                        * current.  khubd will turn the power back on.
+                        */
+                       if (HCS_PPC (ehci->hcs_params)){
+                               ehci_writel(ehci,
+                                       temp & ~(PORT_RWC_BITS | PORT_POWER),
+                                       status_reg);
+                       }
+               }
+
                /* whoever resumes must GetPortStatus to complete it!! */
                if (temp & PORT_RESUME) {
 
index a8ba2e1497a4fb6d9f7b46bc6068b0cc6fd56371..8816d09903d0b11317e1ddcbaacc479158365c1d 100644 (file)
@@ -27,7 +27,7 @@
  *       need to use dma_pool or dma_alloc_coherent
  *     - driver buffers, read/written by HC ... single shot DMA mapped
  *
- * There's also PCI "register" data, which is memory mapped.
+ * There's also "register" data (e.g. PCI or SOC), which is memory mapped.
  * No memory seen by this driver is pageable.
  */
 
 
 /* Allocate the key transfer structures from the previously allocated pool */
 
-static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma)
+static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd,
+                                 dma_addr_t dma)
 {
        memset (qtd, 0, sizeof *qtd);
        qtd->qtd_dma = dma;
        qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
-       qtd->hw_next = EHCI_LIST_END;
-       qtd->hw_alt_next = EHCI_LIST_END;
+       qtd->hw_next = EHCI_LIST_END(ehci);
+       qtd->hw_alt_next = EHCI_LIST_END(ehci);
        INIT_LIST_HEAD (&qtd->qtd_list);
 }
 
@@ -52,7 +53,7 @@ static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags)
 
        qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma);
        if (qtd != NULL) {
-               ehci_qtd_init (qtd, dma);
+               ehci_qtd_init(ehci, qtd, dma);
        }
        return qtd;
 }
@@ -63,9 +64,8 @@ static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
 }
 
 
-static void qh_destroy (struct kref *kref)
+static void qh_destroy(struct ehci_qh *qh)
 {
-       struct ehci_qh *qh = container_of(kref, struct ehci_qh, kref);
        struct ehci_hcd *ehci = qh->ehci;
 
        /* clean qtds first, and know this is not linked */
@@ -89,11 +89,14 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
                return qh;
 
        memset (qh, 0, sizeof *qh);
-       kref_init(&qh->kref);
+       qh->refcount = 1;
        qh->ehci = ehci;
        qh->qh_dma = dma;
        // INIT_LIST_HEAD (&qh->qh_list);
        INIT_LIST_HEAD (&qh->qtd_list);
+#ifdef CONFIG_CPU_FREQ
+       INIT_LIST_HEAD (&qh->split_intr_qhs);
+#endif
 
        /* dummy td enables safe urb queuing */
        qh->dummy = ehci_qtd_alloc (ehci, flags);
@@ -108,13 +111,15 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
 /* to share a qh (cpu threads, or hc) */
 static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
 {
-       kref_get(&qh->kref);
+       WARN_ON(!qh->refcount);
+       qh->refcount++;
        return qh;
 }
 
 static inline void qh_put (struct ehci_qh *qh)
 {
-       kref_put(&qh->kref, qh_destroy);
+       if (!--qh->refcount)
+               qh_destroy(qh);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -217,7 +222,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
                goto fail;
        }
        for (i = 0; i < ehci->periodic_size; i++)
-               ehci->periodic [i] = EHCI_LIST_END;
+               ehci->periodic [i] = EHCI_LIST_END(ehci);
 
        /* software shadow of hardware table */
        ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags);
index 12edc723ec73e41261be2eb1bf25aee451fc1a92..a7816e392a8520fb264ee961aafbf4ba14b993eb 100644 (file)
@@ -149,8 +149,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                 * fixed in newer silicon.
                 */
                case 0x0068:
-                       pci_read_config_dword(pdev, PCI_REVISION_ID, &temp);
-                       if ((temp & 0xff) < 0xa4)
+                       if (pdev->revision < 0xa4)
                                ehci->no_selective_suspend = 1;
                        break;
                }
@@ -313,13 +312,14 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
        ehci_work(ehci);
        spin_unlock_irq(&ehci->lock);
 
-       /* here we "know" root ports should always stay powered */
-       ehci_port_power(ehci, 1);
-
        ehci_writel(ehci, ehci->command, &ehci->regs->command);
        ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
        ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
 
+       /* here we "know" root ports should always stay powered */
+       ehci_port_power(ehci, 1);
+       ehci_handover_companion_ports(ehci);
+
        hcd->state = HC_STATE_SUSPENDED;
        return 0;
 }
diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c
new file mode 100644 (file)
index 0000000..c2cedb0
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * EHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 2006-2007 Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * Bus Glue for PPC On-Chip EHCI driver
+ * Tested on AMCC 440EPx
+ *
+ * Based on "ehci-au12xx.c" by David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/platform_device.h>
+
+extern int usb_disabled(void);
+
+/**
+ * usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ */
+int usb_ehci_ppc_soc_probe(const struct hc_driver *driver,
+                          struct usb_hcd **hcd_out,
+                          struct platform_device *dev)
+{
+       int retval;
+       struct usb_hcd *hcd;
+       struct ehci_hcd *ehci;
+
+       if (dev->resource[1].flags != IORESOURCE_IRQ) {
+               pr_debug("resource[1] is not IORESOURCE_IRQ");
+               retval = -ENOMEM;
+       }
+       hcd = usb_create_hcd(driver, &dev->dev, "PPC-SOC EHCI");
+       if (!hcd)
+               return -ENOMEM;
+       hcd->rsrc_start = dev->resource[0].start;
+       hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+
+       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+               pr_debug("request_mem_region failed");
+               retval = -EBUSY;
+               goto err1;
+       }
+
+       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+       if (!hcd->regs) {
+               pr_debug("ioremap failed");
+               retval = -ENOMEM;
+               goto err2;
+       }
+
+       ehci = hcd_to_ehci(hcd);
+       ehci->big_endian_mmio = 1;
+       ehci->big_endian_desc = 1;
+       ehci->caps = hcd->regs;
+       ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+
+       /* cache this readonly data; minimize chip reads */
+       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+#if defined(CONFIG_440EPX)
+       /*
+        * 440EPx Errata USBH_3
+        * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
+        */
+       out_be32((void *)((ulong)(&ehci->regs->command) + 0x8c), (1 << 0));
+       ehci_dbg(ehci, "Break Memory Transfer (BMT) has beed enabled!\n");
+#endif
+
+       retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);
+       if (retval == 0)
+               return retval;
+
+       iounmap(hcd->regs);
+err2:
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+       usb_put_hcd(hcd);
+       return retval;
+}
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_ehci_hcd_ppc_soc_remove - shutdown processing for PPC-SoC-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_ehci_hcd_ppc_soc_probe(), first invoking
+ * the HCD's stop() method.  It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ */
+void usb_ehci_ppc_soc_remove(struct usb_hcd *hcd, struct platform_device *dev)
+{
+       usb_remove_hcd(hcd);
+       iounmap(hcd->regs);
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+       usb_put_hcd(hcd);
+}
+
+static const struct hc_driver ehci_ppc_soc_hc_driver = {
+       .description = hcd_name,
+       .product_desc = "PPC-SOC EHCI",
+       .hcd_priv_size = sizeof(struct ehci_hcd),
+
+       /*
+        * generic hardware linkage
+        */
+       .irq = ehci_irq,
+       .flags = HCD_MEMORY | HCD_USB2,
+
+       /*
+        * basic lifecycle operations
+        */
+       .reset = ehci_init,
+       .start = ehci_run,
+       .stop = ehci_stop,
+       .shutdown = ehci_shutdown,
+
+       /*
+        * managing i/o requests and associated device resources
+        */
+       .urb_enqueue = ehci_urb_enqueue,
+       .urb_dequeue = ehci_urb_dequeue,
+       .endpoint_disable = ehci_endpoint_disable,
+
+       /*
+        * scheduling support
+        */
+       .get_frame_number = ehci_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_status_data = ehci_hub_status_data,
+       .hub_control = ehci_hub_control,
+#ifdef CONFIG_PM
+       .hub_suspend = ehci_hub_suspend,
+       .hub_resume = ehci_hub_resume,
+#endif
+};
+
+static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = NULL;
+       int ret;
+
+       pr_debug("In ehci_hcd_ppc_soc_drv_probe\n");
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       ret = usb_ehci_ppc_soc_probe(&ehci_ppc_soc_hc_driver, &hcd, pdev);
+       return ret;
+}
+
+static int ehci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+       usb_ehci_ppc_soc_remove(hcd, pdev);
+       return 0;
+}
+
+MODULE_ALIAS("ppc-soc-ehci");
+static struct platform_driver ehci_ppc_soc_driver = {
+       .probe = ehci_hcd_ppc_soc_drv_probe,
+       .remove = ehci_hcd_ppc_soc_drv_remove,
+       .shutdown = usb_hcd_platform_shutdown,
+       .driver = {
+               .name = "ppc-soc-ehci",
+               .bus = &platform_bus_type
+       }
+};
index 37b83ba099695d7cc5dc51fb6ebb94ee8e26c8ec..829fe649a981fdc03ad6f5cb64df4f9f0b8e4024 100644 (file)
@@ -18,6 +18,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <asm/firmware.h>
 #include <asm/ps3.h>
 
 static int ps3_ehci_hc_reset(struct usb_hcd *hcd)
@@ -73,7 +74,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
 #endif
 };
 
-static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
+static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
 {
        int result;
        struct usb_hcd *hcd;
@@ -85,13 +86,30 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
                goto fail_start;
        }
 
+       result = ps3_open_hv_device(dev);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed\n",
+                       __func__, __LINE__);
+               goto fail_open;
+       }
+
+       result = ps3_dma_region_create(dev->d_region);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
+                       "(%d)\n", __func__, __LINE__, result);
+               BUG_ON("check region type");
+               goto fail_dma_region;
+       }
+
        result = ps3_mmio_region_create(dev->m_region);
 
        if (result) {
                dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n",
                        __func__, __LINE__);
                result = -EPERM;
-               goto fail_mmio;
+               goto fail_mmio_region;
        }
 
        dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
@@ -120,6 +138,11 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
 
        hcd->rsrc_start = dev->m_region->lpar_addr;
        hcd->rsrc_len = dev->m_region->len;
+
+       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name))
+               dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n",
+                       __func__, __LINE__);
+
        hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len);
 
        if (!hcd->regs) {
@@ -153,34 +176,73 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
 fail_add_hcd:
        iounmap(hcd->regs);
 fail_ioremap:
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
 fail_create_hcd:
        ps3_io_irq_destroy(virq);
 fail_irq:
        ps3_free_mmio_region(dev->m_region);
-fail_mmio:
+fail_mmio_region:
+       ps3_dma_region_free(dev->d_region);
+fail_dma_region:
+       ps3_close_hv_device(dev);
+fail_open:
 fail_start:
        return result;
 }
 
-static int ps3_ehci_sb_remove(struct ps3_system_bus_device *dev)
+static int ps3_ehci_remove(struct ps3_system_bus_device *dev)
 {
+       unsigned int tmp;
        struct usb_hcd *hcd =
                (struct usb_hcd *)ps3_system_bus_get_driver_data(dev);
 
-       usb_put_hcd(hcd);
+       BUG_ON(!hcd);
+
+       dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs);
+       dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq);
+
+       tmp = hcd->irq;
+
+       usb_remove_hcd(hcd);
+
        ps3_system_bus_set_driver_data(dev, NULL);
 
+       BUG_ON(!hcd->regs);
+       iounmap(hcd->regs);
+
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+       usb_put_hcd(hcd);
+
+       ps3_io_irq_destroy(tmp);
+       ps3_free_mmio_region(dev->m_region);
+
+       ps3_dma_region_free(dev->d_region);
+       ps3_close_hv_device(dev);
+
        return 0;
 }
 
-MODULE_ALIAS("ps3-ehci");
+static int ps3_ehci_driver_register(struct ps3_system_bus_driver *drv)
+{
+       return firmware_has_feature(FW_FEATURE_PS3_LV1)
+               ? ps3_system_bus_driver_register(drv)
+               : 0;
+}
+
+static void ps3_ehci_driver_unregister(struct ps3_system_bus_driver *drv)
+{
+       if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+               ps3_system_bus_driver_unregister(drv);
+}
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_EHCI);
 
-static struct ps3_system_bus_driver ps3_ehci_sb_driver = {
+static struct ps3_system_bus_driver ps3_ehci_driver = {
+       .core.name = "ps3-ehci-driver",
+       .core.owner = THIS_MODULE,
        .match_id = PS3_MATCH_ID_EHCI,
-       .core = {
-               .name = "ps3-ehci-driver",
-       },
-       .probe = ps3_ehci_sb_probe,
-       .remove = ps3_ehci_sb_remove,
+       .probe = ps3_ehci_probe,
+       .remove = ps3_ehci_remove,
+       .shutdown = ps3_ehci_remove,
 };
index e7fbbd00e7cd78a95776264a7c12033d5fa2a3a9..2284028f8aa5e2056d0d309effb03173c9b4ea3f 100644 (file)
 /* fill a qtd, returning how much of the buffer we were able to queue up */
 
 static int
-qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
-               int token, int maxpacket)
+qtd_fill(struct ehci_hcd *ehci, struct ehci_qtd *qtd, dma_addr_t buf,
+                 size_t len, int token, int maxpacket)
 {
        int     i, count;
        u64     addr = buf;
 
        /* one buffer entry per 4K ... first might be short or unaligned */
-       qtd->hw_buf [0] = cpu_to_le32 ((u32)addr);
-       qtd->hw_buf_hi [0] = cpu_to_le32 ((u32)(addr >> 32));
+       qtd->hw_buf[0] = cpu_to_hc32(ehci, (u32)addr);
+       qtd->hw_buf_hi[0] = cpu_to_hc32(ehci, (u32)(addr >> 32));
        count = 0x1000 - (buf & 0x0fff);        /* rest of that page */
        if (likely (len < count))               /* ... iff needed */
                count = len;
@@ -62,8 +62,9 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
                /* per-qtd limit: from 16K to 20K (best alignment) */
                for (i = 1; count < len && i < 5; i++) {
                        addr = buf;
-                       qtd->hw_buf [i] = cpu_to_le32 ((u32)addr);
-                       qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32));
+                       qtd->hw_buf[i] = cpu_to_hc32(ehci, (u32)addr);
+                       qtd->hw_buf_hi[i] = cpu_to_hc32(ehci,
+                                       (u32)(addr >> 32));
                        buf += 0x1000;
                        if ((count + 0x1000) < len)
                                count += 0x1000;
@@ -75,7 +76,7 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
                if (count != len)
                        count -= (count % maxpacket);
        }
-       qtd->hw_token = cpu_to_le32 ((count << 16) | token);
+       qtd->hw_token = cpu_to_hc32(ehci, (count << 16) | token);
        qtd->length = count;
 
        return count;
@@ -89,28 +90,28 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
        /* writes to an active overlay are unsafe */
        BUG_ON(qh->qh_state != QH_STATE_IDLE);
 
-       qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma);
-       qh->hw_alt_next = EHCI_LIST_END;
+       qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
+       qh->hw_alt_next = EHCI_LIST_END(ehci);
 
        /* Except for control endpoints, we make hardware maintain data
         * toggle (like OHCI) ... here (re)initialize the toggle in the QH,
         * and set the pseudo-toggle in udev. Only usb_clear_halt() will
         * ever clear it.
         */
-       if (!(qh->hw_info1 & cpu_to_le32(1 << 14))) {
+       if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
                unsigned        is_out, epnum;
 
-               is_out = !(qtd->hw_token & cpu_to_le32(1 << 8));
-               epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f;
+               is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
+               epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
                if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
-                       qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE);
+                       qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
                        usb_settoggle (qh->dev, epnum, is_out, 1);
                }
        }
 
        /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
        wmb ();
-       qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING);
+       qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
 }
 
 /* if it weren't for a common silicon quirk (writing the dummy into the qh
@@ -128,7 +129,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
                qtd = list_entry (qh->qtd_list.next,
                                struct ehci_qtd, qtd_list);
                /* first qtd may already be partially processed */
-               if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current)
+               if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw_current)
                        qtd = NULL;
        }
 
@@ -222,7 +223,7 @@ __acquires(ehci->lock)
                struct ehci_qh  *qh = (struct ehci_qh *) urb->hcpriv;
 
                /* S-mask in a QH means it's an interrupt urb */
-               if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) {
+               if ((qh->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
 
                        /* ... update hc-wide periodic stats (for usbfs) */
                        ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
@@ -277,7 +278,6 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
  * Chases up to qh->hw_current.  Returns number of completions called,
  * indicating how much "real" work we did.
  */
-#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT)
 static unsigned
 qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
@@ -287,6 +287,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
        unsigned                count = 0;
        int                     do_status = 0;
        u8                      state;
+       u32                     halt = HALT_BIT(ehci);
 
        if (unlikely (list_empty (&qh->qtd_list)))
                return count;
@@ -311,6 +312,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                struct urb      *urb;
                u32             token = 0;
 
+               /* ignore QHs that are currently inactive */
+               if (qh->hw_info1 & __constant_cpu_to_le32(QH_INACTIVATE))
+                       break;
+
                qtd = list_entry (entry, struct ehci_qtd, qtd_list);
                urb = qtd->urb;
 
@@ -330,7 +335,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
                /* hardware copies qtd out of qh overlay */
                rmb ();
-               token = le32_to_cpu (qtd->hw_token);
+               token = hc32_to_cpu(ehci, qtd->hw_token);
 
                /* always clean up qtds the hc de-activated */
                if ((token & QTD_STS_ACTIVE) == 0) {
@@ -342,7 +347,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                         * that silicon quirk can kick in with this dummy too.
                         */
                        } else if (IS_SHORT_READ (token)
-                                       && !(qtd->hw_alt_next & EHCI_LIST_END)) {
+                                       && !(qtd->hw_alt_next
+                                               & EHCI_LIST_END(ehci))) {
                                stopped = 1;
                                goto halt;
                        }
@@ -374,17 +380,17 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
                        /* token in overlay may be most current */
                        if (state == QH_STATE_IDLE
-                                       && cpu_to_le32 (qtd->qtd_dma)
+                                       && cpu_to_hc32(ehci, qtd->qtd_dma)
                                                == qh->hw_current)
-                               token = le32_to_cpu (qh->hw_token);
+                               token = hc32_to_cpu(ehci, qh->hw_token);
 
                        /* force halt for unlinked or blocked qh, so we'll
                         * patch the qh later and so that completions can't
                         * activate it while we "know" it's stopped.
                         */
-                       if ((HALT_BIT & qh->hw_token) == 0) {
+                       if ((halt & qh->hw_token) == 0) {
 halt:
-                               qh->hw_token |= HALT_BIT;
+                               qh->hw_token |= halt;
                                wmb ();
                        }
                }
@@ -419,7 +425,7 @@ halt:
         * it after fault cleanup, or recovering from silicon wrongly
         * overlaying the dummy qtd (which reduces DMA chatter).
         */
-       if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END) {
+       if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) {
                switch (state) {
                case QH_STATE_IDLE:
                        qh_refresh(ehci, qh);
@@ -428,7 +434,7 @@ halt:
                        /* should be rare for periodic transfers,
                         * except maybe high bandwidth ...
                         */
-                       if ((__constant_cpu_to_le32 (QH_SMASK)
+                       if ((cpu_to_hc32(ehci, QH_SMASK)
                                        & qh->hw_info2) != 0) {
                                intr_deschedule (ehci, qh);
                                (void) qh_schedule (ehci, qh);
@@ -502,8 +508,9 @@ qh_urb_transaction (
        is_input = usb_pipein (urb->pipe);
        if (usb_pipecontrol (urb->pipe)) {
                /* SETUP pid */
-               qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
-                       token | (2 /* "setup" */ << 8), 8);
+               qtd_fill(ehci, qtd, urb->setup_dma,
+                               sizeof (struct usb_ctrlrequest),
+                               token | (2 /* "setup" */ << 8), 8);
 
                /* ... and always at least one more pid */
                token ^= QTD_TOGGLE;
@@ -512,7 +519,7 @@ qh_urb_transaction (
                if (unlikely (!qtd))
                        goto cleanup;
                qtd->urb = urb;
-               qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+               qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
                list_add_tail (&qtd->qtd_list, head);
 
                /* for zero length DATA stages, STATUS is always IN */
@@ -539,7 +546,7 @@ qh_urb_transaction (
        for (;;) {
                int this_qtd_len;
 
-               this_qtd_len = qtd_fill (qtd, buf, len, token, maxpacket);
+               this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket);
                len -= this_qtd_len;
                buf += this_qtd_len;
                if (is_input)
@@ -557,7 +564,7 @@ qh_urb_transaction (
                if (unlikely (!qtd))
                        goto cleanup;
                qtd->urb = urb;
-               qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+               qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
                list_add_tail (&qtd->qtd_list, head);
        }
 
@@ -566,7 +573,7 @@ qh_urb_transaction (
         */
        if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
                                || usb_pipecontrol (urb->pipe)))
-               qtd->hw_alt_next = EHCI_LIST_END;
+               qtd->hw_alt_next = EHCI_LIST_END(ehci);
 
        /*
         * control requests may need a terminating data "status" ack;
@@ -590,17 +597,17 @@ qh_urb_transaction (
                        if (unlikely (!qtd))
                                goto cleanup;
                        qtd->urb = urb;
-                       qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+                       qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
                        list_add_tail (&qtd->qtd_list, head);
 
                        /* never any data in such packets */
-                       qtd_fill (qtd, 0, 0, token, 0);
+                       qtd_fill(ehci, qtd, 0, 0, token, 0);
                }
        }
 
        /* by default, enable interrupt on urb completion */
        if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
-               qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
+               qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC);
        return head;
 
 cleanup:
@@ -769,8 +776,8 @@ done:
 
        /* init as live, toggle clear, advance to dummy */
        qh->qh_state = QH_STATE_IDLE;
-       qh->hw_info1 = cpu_to_le32 (info1);
-       qh->hw_info2 = cpu_to_le32 (info2);
+       qh->hw_info1 = cpu_to_hc32(ehci, info1);
+       qh->hw_info2 = cpu_to_hc32(ehci, info2);
        usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
        qh_refresh (ehci, qh);
        return qh;
@@ -782,7 +789,7 @@ done:
 
 static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-       __le32          dma = QH_NEXT (qh->qh_dma);
+       __hc32          dma = QH_NEXT(ehci, qh->qh_dma);
        struct ehci_qh  *head;
 
        /* (re)start the async schedule? */
@@ -820,8 +827,6 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 /*-------------------------------------------------------------------------*/
 
-#define        QH_ADDR_MASK    __constant_cpu_to_le32(0x7f)
-
 /*
  * For control/bulk/interrupt, return QH with these TDs appended.
  * Allocates and initializes the QH if necessary.
@@ -837,6 +842,7 @@ static struct ehci_qh *qh_append_tds (
 )
 {
        struct ehci_qh          *qh = NULL;
+       u32                     qh_addr_mask = cpu_to_hc32(ehci, 0x7f);
 
        qh = (struct ehci_qh *) *ptr;
        if (unlikely (qh == NULL)) {
@@ -858,7 +864,7 @@ static struct ehci_qh *qh_append_tds (
 
                         /* usb_reset_device() briefly reverts to address 0 */
                         if (usb_pipedevice (urb->pipe) == 0)
-                                qh->hw_info1 &= ~QH_ADDR_MASK;
+                                qh->hw_info1 &= ~qh_addr_mask;
                }
 
                /* just one way to queue requests: swap with the dummy qtd.
@@ -867,7 +873,7 @@ static struct ehci_qh *qh_append_tds (
                if (likely (qtd != NULL)) {
                        struct ehci_qtd         *dummy;
                        dma_addr_t              dma;
-                       __le32                  token;
+                       __hc32                  token;
 
                        /* to avoid racing the HC, use the dummy td instead of
                         * the first td of our list (becomes new dummy).  both
@@ -875,7 +881,7 @@ static struct ehci_qh *qh_append_tds (
                         * HC is allowed to fetch the old dummy (4.10.2).
                         */
                        token = qtd->hw_token;
-                       qtd->hw_token = HALT_BIT;
+                       qtd->hw_token = HALT_BIT(ehci);
                        wmb ();
                        dummy = qh->dummy;
 
@@ -887,14 +893,14 @@ static struct ehci_qh *qh_append_tds (
                        list_add (&dummy->qtd_list, qtd_list);
                        __list_splice (qtd_list, qh->qtd_list.prev);
 
-                       ehci_qtd_init (qtd, qtd->qtd_dma);
+                       ehci_qtd_init(ehci, qtd, qtd->qtd_dma);
                        qh->dummy = qtd;
 
                        /* hc must see the new dummy at list end */
                        dma = qtd->qtd_dma;
                        qtd = list_entry (qh->qtd_list.prev,
                                        struct ehci_qtd, qtd_list);
-                       qtd->hw_next = QTD_NEXT (dma);
+                       qtd->hw_next = QTD_NEXT(ehci, dma);
 
                        /* let the hc process these next qtds */
                        wmb ();
@@ -970,7 +976,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
 
        timer_action_done (ehci, TIMER_IAA_WATCHDOG);
 
-       // qh->hw_next = cpu_to_le32 (qh->qh_dma);
+       // qh->hw_next = cpu_to_hc32(qh->qh_dma);
        qh->qh_state = QH_STATE_IDLE;
        qh->qh_next.qh = NULL;
        qh_put (qh);                    // refcount from reclaim
index 7b5ae7111f2311609436a2b403f1eec60fdaecd0..d4a8ace496769308338bce8e081511d80032e1d6 100644 (file)
@@ -44,9 +44,10 @@ static int ehci_get_frame (struct usb_hcd *hcd);
  * @tag: hardware tag for type of this record
  */
 static union ehci_shadow *
-periodic_next_shadow (union ehci_shadow *periodic, __le32 tag)
+periodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic,
+               __hc32 tag)
 {
-       switch (tag) {
+       switch (hc32_to_cpu(ehci, tag)) {
        case Q_TYPE_QH:
                return &periodic->qh->qh_next;
        case Q_TYPE_FSTN:
@@ -62,13 +63,14 @@ periodic_next_shadow (union ehci_shadow *periodic, __le32 tag)
 /* caller must hold ehci->lock */
 static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
 {
-       union ehci_shadow       *prev_p = &ehci->pshadow [frame];
-       __le32                  *hw_p = &ehci->periodic [frame];
+       union ehci_shadow       *prev_p = &ehci->pshadow[frame];
+       __hc32                  *hw_p = &ehci->periodic[frame];
        union ehci_shadow       here = *prev_p;
 
        /* find predecessor of "ptr"; hw and shadow lists are in sync */
        while (here.ptr && here.ptr != ptr) {
-               prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p));
+               prev_p = periodic_next_shadow(ehci, prev_p,
+                               Q_NEXT_TYPE(ehci, *hw_p));
                hw_p = here.hw_next;
                here = *prev_p;
        }
@@ -79,7 +81,8 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
        /* update shadow and hardware lists ... the old "next" pointers
         * from ptr may still be in use, the caller updates them.
         */
-       *prev_p = *periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
+       *prev_p = *periodic_next_shadow(ehci, &here,
+                       Q_NEXT_TYPE(ehci, *hw_p));
        *hw_p = *here.hw_next;
 }
 
@@ -87,18 +90,19 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
 static unsigned short
 periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 {
-       __le32                  *hw_p = &ehci->periodic [frame];
+       __hc32                  *hw_p = &ehci->periodic [frame];
        union ehci_shadow       *q = &ehci->pshadow [frame];
        unsigned                usecs = 0;
 
        while (q->ptr) {
-               switch (Q_NEXT_TYPE (*hw_p)) {
+               switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
                case Q_TYPE_QH:
                        /* is it in the S-mask? */
-                       if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe))
+                       if (q->qh->hw_info2 & cpu_to_hc32(ehci, 1 << uframe))
                                usecs += q->qh->usecs;
                        /* ... or C-mask? */
-                       if (q->qh->hw_info2 & cpu_to_le32 (1 << (8 + uframe)))
+                       if (q->qh->hw_info2 & cpu_to_hc32(ehci,
+                                       1 << (8 + uframe)))
                                usecs += q->qh->c_usecs;
                        hw_p = &q->qh->hw_next;
                        q = &q->qh->qh_next;
@@ -108,7 +112,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
                        /* for "save place" FSTNs, count the relevant INTR
                         * bandwidth from the previous frame
                         */
-                       if (q->fstn->hw_prev != EHCI_LIST_END) {
+                       if (q->fstn->hw_prev != EHCI_LIST_END(ehci)) {
                                ehci_dbg (ehci, "ignoring FSTN cost ...\n");
                        }
                        hw_p = &q->fstn->hw_next;
@@ -121,9 +125,10 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
                        break;
                case Q_TYPE_SITD:
                        /* is it in the S-mask?  (count SPLIT, DATA) */
-                       if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) {
+                       if (q->sitd->hw_uframe & cpu_to_hc32(ehci,
+                                       1 << uframe)) {
                                if (q->sitd->hw_fullspeed_ep &
-                                               __constant_cpu_to_le32 (1<<31))
+                                               cpu_to_hc32(ehci, 1<<31))
                                        usecs += q->sitd->stream->usecs;
                                else    /* worst case for OUT start-split */
                                        usecs += HS_USECS_ISO (188);
@@ -131,7 +136,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 
                        /* ... C-mask?  (count CSPLIT, DATA) */
                        if (q->sitd->hw_uframe &
-                                       cpu_to_le32 (1 << (8 + uframe))) {
+                                       cpu_to_hc32(ehci, 1 << (8 + uframe))) {
                                /* worst case for IN complete-split */
                                usecs += q->sitd->stream->c_usecs;
                        }
@@ -173,9 +178,9 @@ static int same_tt (struct usb_device *dev1, struct usb_device *dev2)
  * will cause a transfer in "B-frame" uframe 0.  "B-frames" lag
  * "H-frames" by 1 uframe.  See the EHCI spec sec 4.5 and figure 4.7.
  */
-static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __le32 mask)
+static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)
 {
-       unsigned char smask = QH_SMASK & le32_to_cpu(mask);
+       unsigned char smask = QH_SMASK & hc32_to_cpu(ehci, mask);
        if (!smask) {
                ehci_err(ehci, "invalid empty smask!\n");
                /* uframe 7 can't have bw so this will indicate failure */
@@ -217,14 +222,14 @@ periodic_tt_usecs (
        unsigned short tt_usecs[8]
 )
 {
-       __le32                  *hw_p = &ehci->periodic [frame];
+       __hc32                  *hw_p = &ehci->periodic [frame];
        union ehci_shadow       *q = &ehci->pshadow [frame];
        unsigned char           uf;
 
        memset(tt_usecs, 0, 16);
 
        while (q->ptr) {
-               switch (Q_NEXT_TYPE(*hw_p)) {
+               switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
                case Q_TYPE_ITD:
                        hw_p = &q->itd->hw_next;
                        q = &q->itd->itd_next;
@@ -247,8 +252,8 @@ periodic_tt_usecs (
                        continue;
                // case Q_TYPE_FSTN:
                default:
-                       ehci_dbg(ehci,
-                                 "ignoring periodic frame %d FSTN\n", frame);
+                       ehci_dbg(ehci, "ignoring periodic frame %d FSTN\n",
+                                       frame);
                        hw_p = &q->fstn->hw_next;
                        q = &q->fstn->fstn_next;
                }
@@ -368,41 +373,42 @@ static int tt_no_collision (
         */
        for (; frame < ehci->periodic_size; frame += period) {
                union ehci_shadow       here;
-               __le32                  type;
+               __hc32                  type;
 
                here = ehci->pshadow [frame];
-               type = Q_NEXT_TYPE (ehci->periodic [frame]);
+               type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]);
                while (here.ptr) {
-                       switch (type) {
+                       switch (hc32_to_cpu(ehci, type)) {
                        case Q_TYPE_ITD:
-                               type = Q_NEXT_TYPE (here.itd->hw_next);
+                               type = Q_NEXT_TYPE(ehci, here.itd->hw_next);
                                here = here.itd->itd_next;
                                continue;
                        case Q_TYPE_QH:
                                if (same_tt (dev, here.qh->dev)) {
                                        u32             mask;
 
-                                       mask = le32_to_cpu (here.qh->hw_info2);
+                                       mask = hc32_to_cpu(ehci,
+                                                       here.qh->hw_info2);
                                        /* "knows" no gap is needed */
                                        mask |= mask >> 8;
                                        if (mask & uf_mask)
                                                break;
                                }
-                               type = Q_NEXT_TYPE (here.qh->hw_next);
+                               type = Q_NEXT_TYPE(ehci, here.qh->hw_next);
                                here = here.qh->qh_next;
                                continue;
                        case Q_TYPE_SITD:
                                if (same_tt (dev, here.sitd->urb->dev)) {
                                        u16             mask;
 
-                                       mask = le32_to_cpu (here.sitd
+                                       mask = hc32_to_cpu(ehci, here.sitd
                                                                ->hw_uframe);
                                        /* FIXME assumes no gap for IN! */
                                        mask |= mask >> 8;
                                        if (mask & uf_mask)
                                                break;
                                }
-                               type = Q_NEXT_TYPE (here.sitd->hw_next);
+                               type = Q_NEXT_TYPE(ehci, here.sitd->hw_next);
                                here = here.sitd->sitd_next;
                                continue;
                        // case Q_TYPE_FSTN:
@@ -473,6 +479,109 @@ static int disable_periodic (struct ehci_hcd *ehci)
 }
 
 /*-------------------------------------------------------------------------*/
+#ifdef CONFIG_CPU_FREQ
+
+static int safe_to_modify_i (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+       int now; /* current (frame * 8) + uframe */
+       int prev_start, next_start; /* uframes from/to split start */
+       int start_uframe = ffs(le32_to_cpup (&qh->hw_info2) & QH_SMASK);
+       int end_uframe = fls((le32_to_cpup (&qh->hw_info2) & QH_CMASK) >> 8);
+       int split_duration = end_uframe - start_uframe;
+
+       now = readl(&ehci->regs->frame_index) % (ehci->periodic_size << 3);
+
+       next_start = ((1024 << 3) + (qh->start << 3) + start_uframe - now)
+                       % (qh->period << 3);
+       prev_start = (qh->period << 3) - next_start;
+
+       /*
+        * Make sure there will be at least one uframe when qh is safe.
+        */
+       if ((qh->period << 3) <= (ehci->i_thresh + 2 + split_duration))
+               /* never safe */
+               return -EINVAL;
+
+       /*
+        * Wait 1 uframe after transaction should have started, to make
+        * sure controller has time to write back overlay, so we can
+        * check QTD_STS_STS to see if transaction is in progress.
+        */
+       if ((next_start > ehci->i_thresh) && (prev_start > 1))
+               /* safe to set "i" bit if split isn't in progress */
+               return (qh->hw_token & STATUS_BIT(ehci)) ? 0 : 1;
+       else
+               return 0;
+}
+
+/* Set inactivate bit for all the split interrupt QHs. */
+static void qh_inactivate_split_intr_qhs (struct ehci_hcd *ehci)
+{
+       struct ehci_qh  *qh;
+       int             not_done, safe;
+       u32             inactivate = INACTIVATE_BIT(ehci);
+       u32             active = ACTIVE_BIT(ehci);
+
+       do {
+               not_done = 0;
+               list_for_each_entry(qh, &ehci->split_intr_qhs,
+                               split_intr_qhs) {
+                       if (qh->hw_info1 & inactivate)
+                               /* already off */
+                               continue;
+                       /*
+                        * To avoid setting "I" after the start split happens,
+                        * don't set it if the QH might be cached in the
+                        * controller.  Some HCs (Broadcom/ServerWorks HT1000)
+                        * will stop in the middle of a split transaction when
+                        * the "I" bit is set.
+                        */
+                       safe = safe_to_modify_i(ehci, qh);
+                       if (safe == 0) {
+                               not_done = 1;
+                       } else if (safe > 0) {
+                               qh->was_active = qh->hw_token & active;
+                               qh->hw_info1 |= inactivate;
+                       }
+               }
+       } while (not_done);
+       wmb();
+}
+
+static void qh_reactivate_split_intr_qhs (struct ehci_hcd *ehci)
+{
+       struct ehci_qh  *qh;
+       u32             token;
+       int             not_done, safe;
+       u32             inactivate = INACTIVATE_BIT(ehci);
+       u32             active = ACTIVE_BIT(ehci);
+       u32             halt = HALT_BIT(ehci);
+
+       do {
+               not_done = 0;
+               list_for_each_entry(qh, &ehci->split_intr_qhs, split_intr_qhs) {
+                       if (!(qh->hw_info1 & inactivate)) /* already on */
+                               continue;
+                       /*
+                        * Don't reactivate if cached, or controller might
+                        * overwrite overlay after we modify it!
+                        */
+                       safe = safe_to_modify_i(ehci, qh);
+                       if (safe == 0) {
+                               not_done = 1;
+                       } else if (safe > 0) {
+                               /* See EHCI 1.0 section 4.15.2.4. */
+                               token = qh->hw_token;
+                               qh->hw_token = (token | halt) & ~active;
+                               wmb();
+                               qh->hw_info1 &= ~inactivate;
+                               wmb();
+                               qh->hw_token = (token & ~halt) | qh->was_active;
+                       }
+               }
+       } while (not_done);
+}
+#endif
 
 /* periodic schedule slots have iso tds (normal or split) first, then a
  * sparse tree for active interrupt transfers.
@@ -487,25 +596,36 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
        dev_dbg (&qh->dev->dev,
                "link qh%d-%04x/%p start %d [%d/%d us]\n",
-               period, le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
+               period, hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
                qh, qh->start, qh->usecs, qh->c_usecs);
 
+#ifdef CONFIG_CPU_FREQ
+       /*
+        * If low/full speed interrupt QHs are inactive (because of
+        * cpufreq changing processor speeds), start QH with I flag set--
+        * it will automatically be cleared when cpufreq is done.
+        */
+       if (ehci->cpufreq_changing)
+               if (!(qh->hw_info1 & (cpu_to_le32(1 << 13))))
+                       qh->hw_info1 |= INACTIVATE_BIT(ehci);
+#endif
+
        /* high bandwidth, or otherwise every microframe */
        if (period == 0)
                period = 1;
 
        for (i = qh->start; i < ehci->periodic_size; i += period) {
-               union ehci_shadow       *prev = &ehci->pshadow [i];
-               __le32                  *hw_p = &ehci->periodic [i];
+               union ehci_shadow       *prev = &ehci->pshadow[i];
+               __hc32                  *hw_p = &ehci->periodic[i];
                union ehci_shadow       here = *prev;
-               __le32                  type = 0;
+               __hc32                  type = 0;
 
                /* skip the iso nodes at list head */
                while (here.ptr) {
-                       type = Q_NEXT_TYPE (*hw_p);
-                       if (type == Q_TYPE_QH)
+                       type = Q_NEXT_TYPE(ehci, *hw_p);
+                       if (type == cpu_to_hc32(ehci, Q_TYPE_QH))
                                break;
-                       prev = periodic_next_shadow (prev, type);
+                       prev = periodic_next_shadow(ehci, prev, type);
                        hw_p = &here.qh->hw_next;
                        here = *prev;
                }
@@ -527,7 +647,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
                                qh->hw_next = *hw_p;
                        wmb ();
                        prev->qh = qh;
-                       *hw_p = QH_NEXT (qh->qh_dma);
+                       *hw_p = QH_NEXT (ehci, qh->qh_dma);
                }
        }
        qh->qh_state = QH_STATE_LINKED;
@@ -538,6 +658,12 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
                ? ((qh->usecs + qh->c_usecs) / qh->period)
                : (qh->usecs * 8);
 
+#ifdef CONFIG_CPU_FREQ
+       /* add qh to list of low/full speed interrupt QHs, if applicable */
+       if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) {
+               list_add(&qh->split_intr_qhs, &ehci->split_intr_qhs);
+       }
+#endif
        /* maybe enable periodic schedule processing */
        if (!ehci->periodic_sched++)
                return enable_periodic (ehci);
@@ -555,7 +681,14 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
        //   and this qh is active in the current uframe
        //   (and overlay token SplitXstate is false?)
        // THEN
-       //   qh->hw_info1 |= __constant_cpu_to_le32 (1 << 7 /* "ignore" */);
+       //   qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */);
+
+#ifdef CONFIG_CPU_FREQ
+       /* remove qh from list of low/full speed interrupt QHs */
+       if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) {
+               list_del_init(&qh->split_intr_qhs);
+       }
+#endif
 
        /* high bandwidth, or otherwise part of every microframe */
        if ((period = qh->period) == 0)
@@ -572,7 +705,7 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
        dev_dbg (&qh->dev->dev,
                "unlink qh%d-%04x/%p start %d [%d/%d us]\n",
                qh->period,
-               le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
+               hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
                qh, qh->start, qh->usecs, qh->c_usecs);
 
        /* qh->qh_next still "live" to HC */
@@ -598,7 +731,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
         * active high speed queues may need bigger delays...
         */
        if (list_empty (&qh->qtd_list)
-                       || (__constant_cpu_to_le32 (QH_CMASK)
+                       || (cpu_to_hc32(ehci, QH_CMASK)
                                        & qh->hw_info2) != 0)
                wait = 2;
        else
@@ -606,7 +739,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
        udelay (wait);
        qh->qh_state = QH_STATE_IDLE;
-       qh->hw_next = EHCI_LIST_END;
+       qh->hw_next = EHCI_LIST_END(ehci);
        wmb ();
 }
 
@@ -663,7 +796,7 @@ static int check_intr_schedule (
        unsigned                frame,
        unsigned                uframe,
        const struct ehci_qh    *qh,
-       __le32                  *c_maskp
+       __hc32                  *c_maskp
 )
 {
        int             retval = -ENOSPC;
@@ -695,7 +828,7 @@ static int check_intr_schedule (
 
                retval = 0;
 
-               *c_maskp = cpu_to_le32 (mask << 8);
+               *c_maskp = cpu_to_hc32(ehci, mask << 8);
        }
 #else
        /* Make sure this tt's buffer is also available for CSPLITs.
@@ -706,7 +839,7 @@ static int check_intr_schedule (
         * one smart pass...
         */
        mask = 0x03 << (uframe + qh->gap_uf);
-       *c_maskp = cpu_to_le32 (mask << 8);
+       *c_maskp = cpu_to_hc32(ehci, mask << 8);
 
        mask |= 1 << uframe;
        if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) {
@@ -726,20 +859,20 @@ done:
 /* "first fit" scheduling policy used the first time through,
  * or when the previous schedule slot can't be re-used.
  */
-static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
+static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
        int             status;
        unsigned        uframe;
-       __le32          c_mask;
+       __hc32          c_mask;
        unsigned        frame;          /* 0..(qh->period - 1), or NO_FRAME */
 
        qh_refresh(ehci, qh);
-       qh->hw_next = EHCI_LIST_END;
+       qh->hw_next = EHCI_LIST_END(ehci);
        frame = qh->start;
 
        /* reuse the previous schedule slots, if we can */
        if (frame < qh->period) {
-               uframe = ffs (le32_to_cpup (&qh->hw_info2) & QH_SMASK);
+               uframe = ffs(hc32_to_cpup(ehci, &qh->hw_info2) & QH_SMASK);
                status = check_intr_schedule (ehci, frame, --uframe,
                                qh, &c_mask);
        } else {
@@ -775,10 +908,10 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
                qh->start = frame;
 
                /* reset S-frame and (maybe) C-frame masks */
-               qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK));
+               qh->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
                qh->hw_info2 |= qh->period
-                       ? cpu_to_le32 (1 << uframe)
-                       : __constant_cpu_to_le32 (QH_SMASK);
+                       ? cpu_to_hc32(ehci, 1 << uframe)
+                       : cpu_to_hc32(ehci, QH_SMASK);
                qh->hw_info2 |= c_mask;
        } else
                ehci_dbg (ehci, "reused qh %p schedule\n", qh);
@@ -808,7 +941,7 @@ static int intr_submit (
        spin_lock_irqsave (&ehci->lock, flags);
 
        if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
-                              &ehci_to_hcd(ehci)->flags))) {
+                       &ehci_to_hcd(ehci)->flags))) {
                status = -ESHUTDOWN;
                goto done;
        }
@@ -898,9 +1031,9 @@ iso_stream_init (
                buf1 |= maxp;
                maxp *= multi;
 
-               stream->buf0 = cpu_to_le32 ((epnum << 8) | dev->devnum);
-               stream->buf1 = cpu_to_le32 (buf1);
-               stream->buf2 = cpu_to_le32 (multi);
+               stream->buf0 = cpu_to_hc32(ehci, (epnum << 8) | dev->devnum);
+               stream->buf1 = cpu_to_hc32(ehci, buf1);
+               stream->buf2 = cpu_to_hc32(ehci, multi);
 
                /* usbfs wants to report the average usecs per frame tied up
                 * when transfers on this endpoint are scheduled ...
@@ -943,7 +1076,7 @@ iso_stream_init (
                bandwidth /= 1 << (interval + 2);
 
                /* stream->splits gets created from raw_mask later */
-               stream->address = cpu_to_le32 (addr);
+               stream->address = cpu_to_hc32(ehci, addr);
        }
        stream->bandwidth = bandwidth;
 
@@ -1077,7 +1210,8 @@ iso_sched_alloc (unsigned packets, gfp_t mem_flags)
 }
 
 static inline void
-itd_sched_init (
+itd_sched_init(
+       struct ehci_hcd         *ehci,
        struct ehci_iso_sched   *iso_sched,
        struct ehci_iso_stream  *stream,
        struct urb              *urb
@@ -1107,7 +1241,7 @@ itd_sched_init (
                                && !(urb->transfer_flags & URB_NO_INTERRUPT))
                        trans |= EHCI_ITD_IOC;
                trans |= length << 16;
-               uframe->transaction = cpu_to_le32 (trans);
+               uframe->transaction = cpu_to_hc32(ehci, trans);
 
                /* might need to cross a buffer page within a uframe */
                uframe->bufp = (buf & ~(u64)0x0fff);
@@ -1149,7 +1283,7 @@ itd_urb_transaction (
        if (unlikely (sched == NULL))
                return -ENOMEM;
 
-       itd_sched_init (sched, stream, urb);
+       itd_sched_init(ehci, sched, stream, urb);
 
        if (urb->interval < 8)
                num_itds = 1 + (sched->span + 7) / 8;
@@ -1167,7 +1301,7 @@ itd_urb_transaction (
                /* prefer previously-allocated itds */
                if (likely (!list_empty(&stream->free_list))) {
                        itd = list_entry (stream->free_list.prev,
-                                        struct ehci_itd, itd_list);
+                                       struct ehci_itd, itd_list);
                        list_del (&itd->itd_list);
                        itd_dma = itd->itd_dma;
                } else
@@ -1294,7 +1428,7 @@ sitd_slot_ok (
                uframe += period_uframes;
        } while (uframe < mod);
 
-       stream->splits = cpu_to_le32(stream->raw_mask << (uframe & 7));
+       stream->splits = cpu_to_hc32(ehci, stream->raw_mask << (uframe & 7));
        return 1;
 }
 
@@ -1415,12 +1549,13 @@ ready:
 /*-------------------------------------------------------------------------*/
 
 static inline void
-itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd)
+itd_init(struct ehci_hcd *ehci, struct ehci_iso_stream *stream,
+               struct ehci_itd *itd)
 {
        int i;
 
        /* it's been recently zeroed */
-       itd->hw_next = EHCI_LIST_END;
+       itd->hw_next = EHCI_LIST_END(ehci);
        itd->hw_bufp [0] = stream->buf0;
        itd->hw_bufp [1] = stream->buf1;
        itd->hw_bufp [2] = stream->buf2;
@@ -1432,7 +1567,8 @@ itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd)
 }
 
 static inline void
-itd_patch (
+itd_patch(
+       struct ehci_hcd         *ehci,
        struct ehci_itd         *itd,
        struct ehci_iso_sched   *iso_sched,
        unsigned                index,
@@ -1447,17 +1583,18 @@ itd_patch (
        uframe &= 0x07;
        itd->index [uframe] = index;
 
-       itd->hw_transaction [uframe] = uf->transaction;
-       itd->hw_transaction [uframe] |= cpu_to_le32 (pg << 12);
-       itd->hw_bufp [pg] |= cpu_to_le32 (uf->bufp & ~(u32)0);
-       itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32));
+       itd->hw_transaction[uframe] = uf->transaction;
+       itd->hw_transaction[uframe] |= cpu_to_hc32(ehci, pg << 12);
+       itd->hw_bufp[pg] |= cpu_to_hc32(ehci, uf->bufp & ~(u32)0);
+       itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(uf->bufp >> 32));
 
        /* iso_frame_desc[].offset must be strictly increasing */
        if (unlikely (uf->cross)) {
                u64     bufp = uf->bufp + 4096;
+
                itd->pg = ++pg;
-               itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0);
-               itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(bufp >> 32));
+               itd->hw_bufp[pg] |= cpu_to_hc32(ehci, bufp & ~(u32)0);
+               itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(bufp >> 32));
        }
 }
 
@@ -1470,7 +1607,7 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
        ehci->pshadow [frame].itd = itd;
        itd->frame = frame;
        wmb ();
-       ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD;
+       ehci->periodic[frame] = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
 }
 
 /* fit urb's itds into the selected schedule slot; activate as needed */
@@ -1515,14 +1652,14 @@ itd_link_urb (
                        list_move_tail (&itd->itd_list, &stream->td_list);
                        itd->stream = iso_stream_get (stream);
                        itd->urb = usb_get_urb (urb);
-                       itd_init (stream, itd);
+                       itd_init (ehci, stream, itd);
                }
 
                uframe = next_uframe & 0x07;
                frame = next_uframe >> 3;
 
                itd->usecs [uframe] = stream->usecs;
-               itd_patch (itd, iso_sched, packet, uframe);
+               itd_patch(ehci, itd, iso_sched, packet, uframe);
 
                next_uframe += stream->interval;
                stream->depth += stream->interval;
@@ -1570,7 +1707,7 @@ itd_complete (
                urb_index = itd->index[uframe];
                desc = &urb->iso_frame_desc [urb_index];
 
-               t = le32_to_cpup (&itd->hw_transaction [uframe]);
+               t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]);
                itd->hw_transaction [uframe] = 0;
                stream->depth -= stream->interval;
 
@@ -1700,7 +1837,8 @@ done:
  */
 
 static inline void
-sitd_sched_init (
+sitd_sched_init(
+       struct ehci_hcd         *ehci,
        struct ehci_iso_sched   *iso_sched,
        struct ehci_iso_stream  *stream,
        struct urb              *urb
@@ -1729,7 +1867,7 @@ sitd_sched_init (
                                && !(urb->transfer_flags & URB_NO_INTERRUPT))
                        trans |= SITD_IOC;
                trans |= length << 16;
-               packet->transaction = cpu_to_le32 (trans);
+               packet->transaction = cpu_to_hc32(ehci, trans);
 
                /* might need to cross a buffer page within a td */
                packet->bufp = buf;
@@ -1765,7 +1903,7 @@ sitd_urb_transaction (
        if (iso_sched == NULL)
                return -ENOMEM;
 
-       sitd_sched_init (iso_sched, stream, urb);
+       sitd_sched_init(ehci, iso_sched, stream, urb);
 
        /* allocate/init sITDs */
        spin_lock_irqsave (&ehci->lock, flags);
@@ -1817,7 +1955,8 @@ sitd_urb_transaction (
 /*-------------------------------------------------------------------------*/
 
 static inline void
-sitd_patch (
+sitd_patch(
+       struct ehci_hcd         *ehci,
        struct ehci_iso_stream  *stream,
        struct ehci_sitd        *sitd,
        struct ehci_iso_sched   *iso_sched,
@@ -1827,20 +1966,20 @@ sitd_patch (
        struct ehci_iso_packet  *uf = &iso_sched->packet [index];
        u64                     bufp = uf->bufp;
 
-       sitd->hw_next = EHCI_LIST_END;
+       sitd->hw_next = EHCI_LIST_END(ehci);
        sitd->hw_fullspeed_ep = stream->address;
        sitd->hw_uframe = stream->splits;
        sitd->hw_results = uf->transaction;
-       sitd->hw_backpointer = EHCI_LIST_END;
+       sitd->hw_backpointer = EHCI_LIST_END(ehci);
 
        bufp = uf->bufp;
-       sitd->hw_buf [0] = cpu_to_le32 (bufp);
-       sitd->hw_buf_hi [0] = cpu_to_le32 (bufp >> 32);
+       sitd->hw_buf[0] = cpu_to_hc32(ehci, bufp);
+       sitd->hw_buf_hi[0] = cpu_to_hc32(ehci, bufp >> 32);
 
-       sitd->hw_buf [1] = cpu_to_le32 (uf->buf1);
+       sitd->hw_buf[1] = cpu_to_hc32(ehci, uf->buf1);
        if (uf->cross)
                bufp += 4096;
-       sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32);
+       sitd->hw_buf_hi[1] = cpu_to_hc32(ehci, bufp >> 32);
        sitd->index = index;
 }
 
@@ -1853,7 +1992,7 @@ sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd)
        ehci->pshadow [frame].sitd = sitd;
        sitd->frame = frame;
        wmb ();
-       ehci->periodic [frame] = cpu_to_le32 (sitd->sitd_dma) | Q_TYPE_SITD;
+       ehci->periodic[frame] = cpu_to_hc32(ehci, sitd->sitd_dma | Q_TYPE_SITD);
 }
 
 /* fit urb's sitds into the selected schedule slot; activate as needed */
@@ -1881,7 +2020,7 @@ sitd_link_urb (
                        urb->dev->devpath, stream->bEndpointAddress & 0x0f,
                        (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
                        (next_uframe >> 3) % ehci->periodic_size,
-                       stream->interval, le32_to_cpu (stream->splits));
+                       stream->interval, hc32_to_cpu(ehci, stream->splits));
                stream->start = jiffies;
        }
        ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -1902,7 +2041,7 @@ sitd_link_urb (
                sitd->stream = iso_stream_get (stream);
                sitd->urb = usb_get_urb (urb);
 
-               sitd_patch (stream, sitd, sched, packet);
+               sitd_patch(ehci, stream, sitd, sched, packet);
                sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size,
                                sitd);
 
@@ -1940,7 +2079,7 @@ sitd_complete (
 
        urb_index = sitd->index;
        desc = &urb->iso_frame_desc [urb_index];
-       t = le32_to_cpup (&sitd->hw_results);
+       t = hc32_to_cpup(ehci, &sitd->hw_results);
 
        /* report transfer status */
        if (t & SITD_ERRS) {
@@ -2095,7 +2234,7 @@ scan_periodic (struct ehci_hcd *ehci)
 
        for (;;) {
                union ehci_shadow       q, *q_p;
-               __le32                  type, *hw_p;
+               __hc32                  type, *hw_p;
                unsigned                uframes;
 
                /* don't scan past the live uframe */
@@ -2113,7 +2252,7 @@ restart:
                q_p = &ehci->pshadow [frame];
                hw_p = &ehci->periodic [frame];
                q.ptr = q_p->ptr;
-               type = Q_NEXT_TYPE (*hw_p);
+               type = Q_NEXT_TYPE(ehci, *hw_p);
                modified = 0;
 
                while (q.ptr != NULL) {
@@ -2122,11 +2261,11 @@ restart:
                        int                     live;
 
                        live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state);
-                       switch (type) {
+                       switch (hc32_to_cpu(ehci, type)) {
                        case Q_TYPE_QH:
                                /* handle any completions */
                                temp.qh = qh_get (q.qh);
-                               type = Q_NEXT_TYPE (q.qh->hw_next);
+                               type = Q_NEXT_TYPE(ehci, q.qh->hw_next);
                                q = q.qh->qh_next;
                                modified = qh_completions (ehci, temp.qh);
                                if (unlikely (list_empty (&temp.qh->qtd_list)))
@@ -2137,10 +2276,10 @@ restart:
                                /* for "save place" FSTNs, look at QH entries
                                 * in the previous frame for completions.
                                 */
-                               if (q.fstn->hw_prev != EHCI_LIST_END) {
+                               if (q.fstn->hw_prev != EHCI_LIST_END(ehci)) {
                                        dbg ("ignoring completions from FSTNs");
                                }
-                               type = Q_NEXT_TYPE (q.fstn->hw_next);
+                               type = Q_NEXT_TYPE(ehci, q.fstn->hw_next);
                                q = q.fstn->fstn_next;
                                break;
                        case Q_TYPE_ITD:
@@ -2148,11 +2287,12 @@ restart:
                                rmb ();
                                for (uf = live ? uframes : 8; uf < 8; uf++) {
                                        if (0 == (q.itd->hw_transaction [uf]
-                                                       & ITD_ACTIVE))
+                                                       & ITD_ACTIVE(ehci)))
                                                continue;
                                        q_p = &q.itd->itd_next;
                                        hw_p = &q.itd->hw_next;
-                                       type = Q_NEXT_TYPE (q.itd->hw_next);
+                                       type = Q_NEXT_TYPE(ehci,
+                                                       q.itd->hw_next);
                                        q = *q_p;
                                        break;
                                }
@@ -2164,23 +2304,24 @@ restart:
                                 */
                                *q_p = q.itd->itd_next;
                                *hw_p = q.itd->hw_next;
-                               type = Q_NEXT_TYPE (q.itd->hw_next);
+                               type = Q_NEXT_TYPE(ehci, q.itd->hw_next);
                                wmb();
                                modified = itd_complete (ehci, q.itd);
                                q = *q_p;
                                break;
                        case Q_TYPE_SITD:
-                               if ((q.sitd->hw_results & SITD_ACTIVE)
+                               if ((q.sitd->hw_results & SITD_ACTIVE(ehci))
                                                && live) {
                                        q_p = &q.sitd->sitd_next;
                                        hw_p = &q.sitd->hw_next;
-                                       type = Q_NEXT_TYPE (q.sitd->hw_next);
+                                       type = Q_NEXT_TYPE(ehci,
+                                                       q.sitd->hw_next);
                                        q = *q_p;
                                        break;
                                }
                                *q_p = q.sitd->sitd_next;
                                *hw_p = q.sitd->hw_next;
-                               type = Q_NEXT_TYPE (q.sitd->hw_next);
+                               type = Q_NEXT_TYPE(ehci, q.sitd->hw_next);
                                wmb();
                                modified = sitd_complete (ehci, q.sitd);
                                q = *q_p;
index 46fa57a520d0d6b37a83c459bf1c2ec869369922..2c68a04230c18f822a72cfce68d79f53fd6cd2f6 100644 (file)
 
 /* definitions used for the EHCI driver */
 
+/*
+ * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
+ * __leXX (normally) or __beXX (given EHCI_BIG_ENDIAN_DESC), depending on
+ * the host controller implementation.
+ *
+ * To facilitate the strongest possible byte-order checking from "sparse"
+ * and so on, we use __leXX unless that's not practical.
+ */
+#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
+typedef __u32 __bitwise __hc32;
+typedef __u16 __bitwise __hc16;
+#else
+#define __hc32 __le32
+#define __hc16 __le16
+#endif
+
 /* statistics can be kept for for tuning/monitoring */
 struct ehci_stats {
        /* irq usage */
@@ -55,6 +71,12 @@ struct ehci_hcd {                    /* one per controller */
        __u32                   hcs_params;     /* cached register copy */
        spinlock_t              lock;
 
+#ifdef CONFIG_CPU_FREQ
+       struct notifier_block   cpufreq_transition;
+       int                     cpufreq_changing;
+       struct list_head        split_intr_qhs;
+#endif
+
        /* async schedule support */
        struct ehci_qh          *async;
        struct ehci_qh          *reclaim;
@@ -64,7 +86,7 @@ struct ehci_hcd {                     /* one per controller */
        /* periodic schedule support */
 #define        DEFAULT_I_TDPS          1024            /* some HCs can do less */
        unsigned                periodic_size;
-       __le32                  *periodic;      /* hw periodic table */
+       __hc32                  *periodic;      /* hw periodic table */
        dma_addr_t              periodic_dma;
        unsigned                i_thresh;       /* uframes HC might cache */
 
@@ -74,11 +96,14 @@ struct ehci_hcd {                   /* one per controller */
 
        /* per root hub port */
        unsigned long           reset_done [EHCI_MAX_ROOT_PORTS];
+
        /* bit vectors (one bit per port) */
        unsigned long           bus_suspended;          /* which ports were
                        already suspended at the start of a bus suspend */
        unsigned long           companion_ports;        /* which ports are
                        dedicated to the companion controller */
+       unsigned long           owned_ports;            /* which ports are
+                       owned by the companion during a bus suspend */
 
        /* per-HC memory pools (could be per-bus, but ...) */
        struct dma_pool         *qh_pool;       /* qh per active urb */
@@ -97,6 +122,7 @@ struct ehci_hcd {                    /* one per controller */
        unsigned                no_selective_suspend:1;
        unsigned                has_fsl_port_bug:1; /* FreeScale */
        unsigned                big_endian_mmio:1;
+       unsigned                big_endian_desc:1;
 
        u8                      sbrn;           /* packed release number */
 
@@ -276,6 +302,12 @@ struct ehci_regs {
 #define PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_OCC)
 } __attribute__ ((packed));
 
+#define USBMODE                0x68            /* USB Device mode */
+#define USBMODE_SDIS   (1<<3)          /* Stream disable */
+#define USBMODE_BE     (1<<2)          /* BE/LE endianness select */
+#define USBMODE_CM_HC  (3<<0)          /* host controller mode */
+#define USBMODE_CM_IDLE        (0<<0)          /* idle state */
+
 /* Appendix C, Debug port ... intended for use with special "debug devices"
  * that can help if there's no serial console.  (nonstandard enumeration.)
  */
@@ -303,7 +335,7 @@ struct ehci_dbg_port {
 
 /*-------------------------------------------------------------------------*/
 
-#define        QTD_NEXT(dma)   cpu_to_le32((u32)dma)
+#define        QTD_NEXT(ehci, dma)     cpu_to_hc32(ehci, (u32)dma)
 
 /*
  * EHCI Specification 0.95 Section 3.5
@@ -315,9 +347,9 @@ struct ehci_dbg_port {
  */
 struct ehci_qtd {
        /* first part defined by EHCI spec */
-       __le32                  hw_next;          /* see EHCI 3.5.1 */
-       __le32                  hw_alt_next;      /* see EHCI 3.5.2 */
-       __le32                  hw_token;         /* see EHCI 3.5.3 */
+       __hc32                  hw_next;        /* see EHCI 3.5.1 */
+       __hc32                  hw_alt_next;    /* see EHCI 3.5.2 */
+       __hc32                  hw_token;       /* see EHCI 3.5.3 */
 #define        QTD_TOGGLE      (1 << 31)       /* data toggle */
 #define        QTD_LENGTH(tok) (((tok)>>16) & 0x7fff)
 #define        QTD_IOC         (1 << 15)       /* interrupt on complete */
@@ -331,8 +363,13 @@ struct ehci_qtd {
 #define        QTD_STS_MMF     (1 << 2)        /* incomplete split transaction */
 #define        QTD_STS_STS     (1 << 1)        /* split transaction state */
 #define        QTD_STS_PING    (1 << 0)        /* issue PING? */
-       __le32                  hw_buf [5];        /* see EHCI 3.5.4 */
-       __le32                  hw_buf_hi [5];        /* Appendix B */
+
+#define ACTIVE_BIT(ehci)       cpu_to_hc32(ehci, QTD_STS_ACTIVE)
+#define HALT_BIT(ehci)         cpu_to_hc32(ehci, QTD_STS_HALT)
+#define STATUS_BIT(ehci)       cpu_to_hc32(ehci, QTD_STS_STS)
+
+       __hc32                  hw_buf [5];        /* see EHCI 3.5.4 */
+       __hc32                  hw_buf_hi [5];        /* Appendix B */
 
        /* the rest is HCD-private */
        dma_addr_t              qtd_dma;                /* qtd address */
@@ -342,26 +379,33 @@ struct ehci_qtd {
 } __attribute__ ((aligned (32)));
 
 /* mask NakCnt+T in qh->hw_alt_next */
-#define QTD_MASK __constant_cpu_to_le32 (~0x1f)
+#define QTD_MASK(ehci) cpu_to_hc32 (ehci, ~0x1f)
 
 #define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1)
 
 /*-------------------------------------------------------------------------*/
 
 /* type tag from {qh,itd,sitd,fstn}->hw_next */
-#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1))
+#define Q_NEXT_TYPE(ehci,dma)  ((dma) & cpu_to_hc32(ehci, 3 << 1))
 
+/*
+ * Now the following defines are not converted using the
+ * __constant_cpu_to_le32() macro anymore, since we have to support
+ * "dynamic" switching between be and le support, so that the driver
+ * can be used on one system with SoC EHCI controller using big-endian
+ * descriptors as well as a normal little-endian PCI EHCI controller.
+ */
 /* values for that type tag */
-#define Q_TYPE_ITD     __constant_cpu_to_le32 (0 << 1)
-#define Q_TYPE_QH      __constant_cpu_to_le32 (1 << 1)
-#define Q_TYPE_SITD    __constant_cpu_to_le32 (2 << 1)
-#define Q_TYPE_FSTN    __constant_cpu_to_le32 (3 << 1)
+#define Q_TYPE_ITD     (0 << 1)
+#define Q_TYPE_QH      (1 << 1)
+#define Q_TYPE_SITD    (2 << 1)
+#define Q_TYPE_FSTN    (3 << 1)
 
 /* next async queue entry, or pointer to interrupt/periodic QH */
-#define        QH_NEXT(dma)    (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
+#define QH_NEXT(ehci,dma)      (cpu_to_hc32(ehci, (((u32)dma)&~0x01f)|Q_TYPE_QH))
 
 /* for periodic/async schedules and qtd lists, mark end of list */
-#define        EHCI_LIST_END   __constant_cpu_to_le32(1) /* "null pointer" to hw */
+#define EHCI_LIST_END(ehci)    cpu_to_hc32(ehci, 1) /* "null pointer" to hw */
 
 /*
  * Entries in periodic shadow table are pointers to one of four kinds
@@ -376,7 +420,7 @@ union ehci_shadow {
        struct ehci_itd         *itd;           /* Q_TYPE_ITD */
        struct ehci_sitd        *sitd;          /* Q_TYPE_SITD */
        struct ehci_fstn        *fstn;          /* Q_TYPE_FSTN */
-       __le32                  *hw_next;       /* (all types) */
+       __hc32                  *hw_next;       /* (all types) */
        void                    *ptr;
 };
 
@@ -392,23 +436,27 @@ union ehci_shadow {
 
 struct ehci_qh {
        /* first part defined by EHCI spec */
-       __le32                  hw_next;         /* see EHCI 3.6.1 */
-       __le32                  hw_info1;        /* see EHCI 3.6.2 */
+       __hc32                  hw_next;        /* see EHCI 3.6.1 */
+       __hc32                  hw_info1;       /* see EHCI 3.6.2 */
 #define        QH_HEAD         0x00008000
-       __le32                  hw_info2;        /* see EHCI 3.6.2 */
+#define        QH_INACTIVATE   0x00000080
+
+#define INACTIVATE_BIT(ehci)   cpu_to_hc32(ehci, QH_INACTIVATE)
+
+       __hc32                  hw_info2;        /* see EHCI 3.6.2 */
 #define        QH_SMASK        0x000000ff
 #define        QH_CMASK        0x0000ff00
 #define        QH_HUBADDR      0x007f0000
 #define        QH_HUBPORT      0x3f800000
 #define        QH_MULT         0xc0000000
-       __le32                  hw_current;      /* qtd list - see EHCI 3.6.4 */
+       __hc32                  hw_current;     /* qtd list - see EHCI 3.6.4 */
 
        /* qtd overlay (hardware parts of a struct ehci_qtd) */
-       __le32                  hw_qtd_next;
-       __le32                  hw_alt_next;
-       __le32                  hw_token;
-       __le32                  hw_buf [5];
-       __le32                  hw_buf_hi [5];
+       __hc32                  hw_qtd_next;
+       __hc32                  hw_alt_next;
+       __hc32                  hw_token;
+       __hc32                  hw_buf [5];
+       __hc32                  hw_buf_hi [5];
 
        /* the rest is HCD-private */
        dma_addr_t              qh_dma;         /* address of qh */
@@ -418,7 +466,14 @@ struct ehci_qh {
        struct ehci_qh          *reclaim;       /* next to reclaim */
 
        struct ehci_hcd         *ehci;
-       struct kref             kref;
+
+       /*
+        * Do NOT use atomic operations for QH refcounting. On some CPUs
+        * (PPC7448 for example), atomic operations cannot be performed on
+        * memory that is cache-inhibited (i.e. being used for DMA).
+        * Spinlocks are used to protect all QH fields.
+        */
+       u32                     refcount;
        unsigned                stamp;
 
        u8                      qh_state;
@@ -437,6 +492,10 @@ struct ehci_qh {
        unsigned short          start;          /* where polling starts */
 #define NO_FRAME ((unsigned short)~0)                  /* pick new start */
        struct usb_device       *dev;           /* access to TT */
+#ifdef CONFIG_CPU_FREQ
+       struct list_head        split_intr_qhs; /* list of split qhs */
+       __le32                  was_active;     /* active bit before "i" set */
+#endif
 } __attribute__ ((aligned (32)));
 
 /*-------------------------------------------------------------------------*/
@@ -445,7 +504,7 @@ struct ehci_qh {
 struct ehci_iso_packet {
        /* These will be copied to iTD when scheduling */
        u64                     bufp;           /* itd->hw_bufp{,_hi}[pg] |= */
-       __le32                  transaction;    /* itd->hw_transaction[i] |= */
+       __hc32                  transaction;    /* itd->hw_transaction[i] |= */
        u8                      cross;          /* buf crosses pages */
        /* for full speed OUT splits */
        u32                     buf1;
@@ -467,8 +526,8 @@ struct ehci_iso_sched {
  */
 struct ehci_iso_stream {
        /* first two fields match QH, but info1 == 0 */
-       __le32                  hw_next;
-       __le32                  hw_info1;
+       __hc32                  hw_next;
+       __hc32                  hw_info1;
 
        u32                     refcount;
        u8                      bEndpointAddress;
@@ -483,7 +542,7 @@ struct ehci_iso_stream {
        unsigned long           start;          /* jiffies */
        unsigned long           rescheduled;
        int                     next_uframe;
-       __le32                  splits;
+       __hc32                  splits;
 
        /* the rest is derived from the endpoint descriptor,
         * trusting urb->interval == f(epdesc->bInterval) and
@@ -497,12 +556,12 @@ struct ehci_iso_stream {
        unsigned                bandwidth;
 
        /* This is used to initialize iTD's hw_bufp fields */
-       __le32                  buf0;
-       __le32                  buf1;
-       __le32                  buf2;
+       __hc32                  buf0;
+       __hc32                  buf1;
+       __hc32                  buf2;
 
        /* this is used to initialize sITD's tt info */
-       __le32                  address;
+       __hc32                  address;
 };
 
 /*-------------------------------------------------------------------------*/
@@ -515,8 +574,8 @@ struct ehci_iso_stream {
  */
 struct ehci_itd {
        /* first part defined by EHCI spec */
-       __le32                  hw_next;           /* see EHCI 3.3.1 */
-       __le32                  hw_transaction [8]; /* see EHCI 3.3.2 */
+       __hc32                  hw_next;           /* see EHCI 3.3.1 */
+       __hc32                  hw_transaction [8]; /* see EHCI 3.3.2 */
 #define EHCI_ISOC_ACTIVE        (1<<31)        /* activate transfer this slot */
 #define EHCI_ISOC_BUF_ERR       (1<<30)        /* Data buffer error */
 #define EHCI_ISOC_BABBLE        (1<<29)        /* babble detected */
@@ -524,10 +583,10 @@ struct ehci_itd {
 #define        EHCI_ITD_LENGTH(tok)    (((tok)>>16) & 0x0fff)
 #define        EHCI_ITD_IOC            (1 << 15)       /* interrupt on complete */
 
-#define ITD_ACTIVE     __constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
+#define ITD_ACTIVE(ehci)       cpu_to_hc32(ehci, EHCI_ISOC_ACTIVE)
 
-       __le32                  hw_bufp [7];    /* see EHCI 3.3.3 */
-       __le32                  hw_bufp_hi [7]; /* Appendix B */
+       __hc32                  hw_bufp [7];    /* see EHCI 3.3.3 */
+       __hc32                  hw_bufp_hi [7]; /* Appendix B */
 
        /* the rest is HCD-private */
        dma_addr_t              itd_dma;        /* for this itd */
@@ -554,11 +613,11 @@ struct ehci_itd {
  */
 struct ehci_sitd {
        /* first part defined by EHCI spec */
-       __le32                  hw_next;
+       __hc32                  hw_next;
 /* uses bit field macros above - see EHCI 0.95 Table 3-8 */
-       __le32                  hw_fullspeed_ep;        /* EHCI table 3-9 */
-       __le32                  hw_uframe;              /* EHCI table 3-10 */
-       __le32                  hw_results;             /* EHCI table 3-11 */
+       __hc32                  hw_fullspeed_ep;        /* EHCI table 3-9 */
+       __hc32                  hw_uframe;              /* EHCI table 3-10 */
+       __hc32                  hw_results;             /* EHCI table 3-11 */
 #define        SITD_IOC        (1 << 31)       /* interrupt on completion */
 #define        SITD_PAGE       (1 << 30)       /* buffer 0/1 */
 #define        SITD_LENGTH(x)  (0x3ff & ((x)>>16))
@@ -570,11 +629,11 @@ struct ehci_sitd {
 #define        SITD_STS_MMF    (1 << 2)        /* incomplete split transaction */
 #define        SITD_STS_STS    (1 << 1)        /* split transaction state */
 
-#define SITD_ACTIVE    __constant_cpu_to_le32(SITD_STS_ACTIVE)
+#define SITD_ACTIVE(ehci)      cpu_to_hc32(ehci, SITD_STS_ACTIVE)
 
-       __le32                  hw_buf [2];             /* EHCI table 3-12 */
-       __le32                  hw_backpointer;         /* EHCI table 3-13 */
-       __le32                  hw_buf_hi [2];          /* Appendix B */
+       __hc32                  hw_buf [2];             /* EHCI table 3-12 */
+       __hc32                  hw_backpointer;         /* EHCI table 3-13 */
+       __hc32                  hw_buf_hi [2];          /* Appendix B */
 
        /* the rest is HCD-private */
        dma_addr_t              sitd_dma;
@@ -599,8 +658,8 @@ struct ehci_sitd {
  * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
  */
 struct ehci_fstn {
-       __le32                  hw_next;        /* any periodic q entry */
-       __le32                  hw_prev;        /* qh or EHCI_LIST_END */
+       __hc32                  hw_next;        /* any periodic q entry */
+       __hc32                  hw_prev;        /* qh or EHCI_LIST_END */
 
        /* the rest is HCD-private */
        dma_addr_t              fstn_dma;
@@ -672,8 +731,21 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
 #define ehci_big_endian_mmio(e)                0
 #endif
 
-static inline unsigned int ehci_readl (const struct ehci_hcd *ehci,
-                                      __u32 __iomem * regs)
+/*
+ * Big-endian read/write functions are arch-specific.
+ * Other arches can be added if/when they're needed.
+ *
+ * REVISIT: arch/powerpc now has readl/writel_be, so the
+ * definition below can die once the 4xx support is
+ * finally ported over.
+ */
+#if defined(CONFIG_PPC)
+#define readl_be(addr)         in_be32((__force unsigned *)addr)
+#define writel_be(val, addr)   out_be32((__force unsigned *)addr, val)
+#endif
+
+static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,
+               __u32 __iomem * regs)
 {
 #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
        return ehci_big_endian_mmio(ehci) ?
@@ -684,8 +756,8 @@ static inline unsigned int ehci_readl (const struct ehci_hcd *ehci,
 #endif
 }
 
-static inline void ehci_writel (const struct ehci_hcd *ehci,
-                               const unsigned int val, __u32 __iomem *regs)
+static inline void ehci_writel(const struct ehci_hcd *ehci,
+               const unsigned int val, __u32 __iomem *regs)
 {
 #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
        ehci_big_endian_mmio(ehci) ?
@@ -698,6 +770,62 @@ static inline void ehci_writel (const struct ehci_hcd *ehci,
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * The AMCC 440EPx not only implements its EHCI registers in big-endian
+ * format, but also its DMA data structures (descriptors).
+ *
+ * EHCI controllers accessed through PCI work normally (little-endian
+ * everywhere), so we won't bother supporting a BE-only mode for now.
+ */
+#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
+#define ehci_big_endian_desc(e)                ((e)->big_endian_desc)
+
+/* cpu to ehci */
+static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x)
+{
+       return ehci_big_endian_desc(ehci)
+               ? (__force __hc32)cpu_to_be32(x)
+               : (__force __hc32)cpu_to_le32(x);
+}
+
+/* ehci to cpu */
+static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x)
+{
+       return ehci_big_endian_desc(ehci)
+               ? be32_to_cpu((__force __be32)x)
+               : le32_to_cpu((__force __le32)x);
+}
+
+static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+{
+       return ehci_big_endian_desc(ehci)
+               ? be32_to_cpup((__force __be32 *)x)
+               : le32_to_cpup((__force __le32 *)x);
+}
+
+#else
+
+/* cpu to ehci */
+static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x)
+{
+       return cpu_to_le32(x);
+}
+
+/* ehci to cpu */
+static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x)
+{
+       return le32_to_cpu(x);
+}
+
+static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+{
+       return le32_to_cpup(x);
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 #ifndef DEBUG
 #define STUB_DEBUG_FILES
 #endif /* DEBUG */
index 273d5ddb72be27ce794c59c3f742409ebf3284b8..6f9e43e9a6cab69072fe420a460d74074f77e6b7 100644 (file)
@@ -23,7 +23,7 @@
 /* debug| print the main components of an URB
  * small: 0) header + data packets 1) just header
  */
-static void __attribute__((unused))
+static void __maybe_unused
 urb_print (struct urb * urb, char * str, int small)
 {
        unsigned int pipe= urb->pipe;
@@ -338,7 +338,7 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label,
 }
 
 /* caller MUST own hcd spinlock if verbose is set! */
-static void __attribute__((unused))
+static void __maybe_unused
 ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
                const struct ed *ed, int verbose)
 {
index a66637e725f3e763b11bbc4257ee55bd64a91c0d..2038125b7f8cf19143d0994b747220648a497282 100644 (file)
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
 #include <linux/reboot.h>
+#include <linux/workqueue.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
-#ifdef CONFIG_PPC_PS3
-#include <asm/firmware.h>
-#endif
 
 #include "../core/hcd.h"
 
@@ -82,6 +80,8 @@ static const char     hcd_name [] = "ohci_hcd";
 static void ohci_dump (struct ohci_hcd *ohci, int verbose);
 static int ohci_init (struct ohci_hcd *ohci);
 static void ohci_stop (struct usb_hcd *hcd);
+static int ohci_restart (struct ohci_hcd *ohci);
+static void ohci_quirk_nec_worker (struct work_struct *work);
 
 #include "ohci-hub.c"
 #include "ohci-dbg.c"
@@ -510,15 +510,7 @@ static int ohci_run (struct ohci_hcd *ohci)
        // flush the writes
        (void) ohci_readl (ohci, &ohci->regs->control);
        msleep(temp);
-       temp = roothub_a (ohci);
-       if (!(temp & RH_A_NPS)) {
-               /* power down each port */
-               for (temp = 0; temp < ohci->num_ports; temp++)
-                       ohci_writel (ohci, RH_PS_LSDA,
-                               &ohci->regs->roothub.portstatus [temp]);
-       }
-       // flush those writes
-       (void) ohci_readl (ohci, &ohci->regs->control);
+
        memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
 
        /* 2msec timelimit here means no irqs/preempt */
@@ -659,9 +651,20 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
        }
 
        if (ints & OHCI_INTR_UE) {
-               disable (ohci);
-               ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
                // e.g. due to PCI Master/Target Abort
+               if (ohci->flags & OHCI_QUIRK_NEC) {
+                       /* Workaround for a silicon bug in some NEC chips used
+                        * in Apple's PowerBooks. Adapted from Darwin code.
+                        */
+                       ohci_err (ohci, "OHCI Unrecoverable Error, scheduling NEC chip restart\n");
+
+                       ohci_writel (ohci, OHCI_INTR_UE, &regs->intrdisable);
+
+                       schedule_work (&ohci->nec_work);
+               } else {
+                       disable (ohci);
+                       ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
+               }
 
                ohci_dump (ohci, 1);
                ohci_usb_reset (ohci);
@@ -763,23 +766,16 @@ static void ohci_stop (struct usb_hcd *hcd)
 /*-------------------------------------------------------------------------*/
 
 /* must not be called from interrupt context */
-
-#ifdef CONFIG_PM
-
 static int ohci_restart (struct ohci_hcd *ohci)
 {
        int temp;
        int i;
        struct urb_priv *priv;
 
-       /* mark any devices gone, so they do nothing till khubd disconnects.
-        * recycle any "live" eds/tds (and urbs) right away.
-        * later, khubd disconnect processing will recycle the other state,
-        * (either as disconnect/reconnect, or maybe someday as a reset).
-        */
        spin_lock_irq(&ohci->lock);
        disable (ohci);
-       usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
+
+       /* Recycle any "live" eds/tds (and urbs). */
        if (!list_empty (&ohci->pending))
                ohci_dbg(ohci, "abort schedule...\n");
        list_for_each_entry (priv, &ohci->pending, pending) {
@@ -826,20 +822,31 @@ static int ohci_restart (struct ohci_hcd *ohci)
        if ((temp = ohci_run (ohci)) < 0) {
                ohci_err (ohci, "can't restart, %d\n", temp);
                return temp;
-       } else {
-               /* here we "know" root ports should always stay powered,
-                * and that if we try to turn them back on the root hub
-                * will respond to CSC processing.
-                */
-               i = ohci->num_ports;
-               while (i--)
-                       ohci_writel (ohci, RH_PS_PSS,
-                               &ohci->regs->roothub.portstatus [i]);
-               ohci_dbg (ohci, "restart complete\n");
        }
+       ohci_dbg(ohci, "restart complete\n");
        return 0;
 }
-#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* NEC workaround */
+static void ohci_quirk_nec_worker(struct work_struct *work)
+{
+       struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work);
+       int status;
+
+       status = ohci_init(ohci);
+       if (status != 0) {
+               ohci_err(ohci, "Restarting NEC controller failed "
+                        "in ohci_init, %d\n", status);
+               return;
+       }
+
+       status = ohci_restart(ohci);
+       if (status != 0)
+               ohci_err(ohci, "Restarting NEC controller failed "
+                        "in ohci_restart, %d\n", status);
+}
 
 /*-------------------------------------------------------------------------*/
 
@@ -917,7 +924,7 @@ MODULE_LICENSE ("GPL");
 
 #ifdef CONFIG_PPC_PS3
 #include "ohci-ps3.c"
-#define PS3_SYSTEM_BUS_DRIVER  ps3_ohci_sb_driver
+#define PS3_SYSTEM_BUS_DRIVER  ps3_ohci_driver
 #endif
 
 #if    !defined(PCI_DRIVER) &&         \
@@ -940,12 +947,9 @@ static int __init ohci_hcd_mod_init(void)
                sizeof (struct ed), sizeof (struct td));
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-       if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
-               retval = ps3_system_bus_driver_register(
-                               &PS3_SYSTEM_BUS_DRIVER);
-               if (retval < 0)
-                       goto error_ps3;
-       }
+       retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
+       if (retval < 0)
+               goto error_ps3;
 #endif
 
 #ifdef PLATFORM_DRIVER
@@ -991,8 +995,7 @@ static int __init ohci_hcd_mod_init(void)
  error_platform:
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-       if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-               ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+       ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
  error_ps3:
 #endif
        return retval;
@@ -1014,8 +1017,7 @@ static void __exit ohci_hcd_mod_exit(void)
        platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-       if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-               ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+       ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ohci_hcd_mod_exit);
index bb9cc595219e84cb0582250dc857d9892a503c0a..48e4b11f4d3ea53a2d837636e5ae72de4a0724af 100644 (file)
@@ -55,8 +55,6 @@ static void dl_done_list (struct ohci_hcd *);
 static void finish_unlinks (struct ohci_hcd *, u16);
 
 #ifdef CONFIG_PM
-static int ohci_restart(struct ohci_hcd *ohci);
-
 static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
 __releases(ohci->lock)
 __acquires(ohci->lock)
@@ -191,6 +189,9 @@ __acquires(ohci->lock)
                        spin_unlock_irq (&ohci->lock);
                        (void) ohci_init (ohci);
                        status = ohci_restart (ohci);
+
+                       usb_root_hub_lost_power(hcd->self.root_hub);
+
                        spin_lock_irq (&ohci->lock);
                }
                return status;
index 2f20d3dc895b8b4a959459573f4089e2014f27f8..450c7b460c5ab092e62ab13828ec41874f483b95 100644 (file)
@@ -28,6 +28,7 @@ static void ohci_hcd_init (struct ohci_hcd *ohci)
        ohci->next_statechange = jiffies;
        spin_lock_init (&ohci->lock);
        INIT_LIST_HEAD (&ohci->pending);
+       INIT_WORK (&ohci->nec_work, ohci_quirk_nec_worker);
 }
 
 /*-------------------------------------------------------------------------*/
index ca62cb583221a877e0f819b27de91a6d7e62d066..a5e2eb85d073bd69cb9e356cffc5f202e489d305 100644 (file)
@@ -111,6 +111,18 @@ static int ohci_quirk_toshiba_scc(struct usb_hcd *hcd)
 #endif
 }
 
+/* Check for NEC chip and apply quirk for allegedly lost interrupts.
+ */
+static int ohci_quirk_nec(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+
+       ohci->flags |= OHCI_QUIRK_NEC;
+       ohci_dbg (ohci, "enabled NEC chipset lost interrupt quirk\n");
+
+       return 0;
+}
+
 /* List of quirks for OHCI */
 static const struct pci_device_id ohci_pci_quirks[] = {
        {
@@ -133,6 +145,10 @@ static const struct pci_device_id ohci_pci_quirks[] = {
                PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, 0x01b6),
                .driver_data = (unsigned long)ohci_quirk_toshiba_scc,
        },
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB),
+               .driver_data = (unsigned long)ohci_quirk_nec,
+       },
        {
                /* Toshiba portege 4000 */
                .vendor         = PCI_VENDOR_ID_AL,
@@ -202,6 +218,42 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
        return ret;
 }
 
+#if    defined(CONFIG_USB_PERSIST) && (defined(CONFIG_USB_EHCI_HCD) || \
+               defined(CONFIG_USB_EHCI_HCD_MODULE))
+
+/* Following a power loss, we must prepare to regain control of the ports
+ * we used to own.  This means turning on the port power before ehci-hcd
+ * tries to switch ownership.
+ *
+ * This isn't a 100% perfect solution.  On most systems the OHCI controllers
+ * lie at lower PCI addresses than the EHCI controller, so they will be
+ * discovered (and hence resumed) first.  But there is no guarantee things
+ * will always work this way.  If the EHCI controller is resumed first and
+ * the OHCI ports are unpowered, then the handover will fail.
+ */
+static void prepare_for_handover(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       int             port;
+
+       /* Here we "know" root ports should always stay powered */
+       ohci_dbg(ohci, "powerup ports\n");
+       for (port = 0; port < ohci->num_ports; port++)
+               ohci_writel(ohci, RH_PS_PPS,
+                               &ohci->regs->roothub.portstatus[port]);
+
+       /* Flush those writes */
+       ohci_readl(ohci, &ohci->regs->control);
+       msleep(20);
+}
+
+#else
+
+static inline void prepare_for_handover(struct usb_hcd *hcd)
+{ }
+
+#endif /* CONFIG_USB_PERSIST etc. */
+
 #ifdef CONFIG_PM
 
 static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
@@ -241,7 +293,10 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
 static int ohci_pci_resume (struct usb_hcd *hcd)
 {
        set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       usb_hcd_resume_root_hub(hcd);
+
+       /* FIXME: we should try to detect loss of VBUS power here */
+       prepare_for_handover(hcd);
+
        return 0;
 }
 
index d601bbb9387bb5205d6c29aed3208a405c186bfc..ca2a6abbc1172e21ab2924920268894f5566dd1e 100644 (file)
@@ -134,7 +134,7 @@ static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind)
 {
        struct i2c_client *c;
 
-       c = (struct i2c_client *)kzalloc(sizeof(*c), GFP_KERNEL);
+       c = kzalloc(sizeof(*c), GFP_KERNEL);
 
        if (!c)
                return -ENOMEM;
index d7cf07288b0bdbea54e444e9d7e862349eaf1b8d..01a0caeaa6bcc9345b74131baa03d3acfb956439 100644 (file)
@@ -18,6 +18,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <asm/firmware.h>
 #include <asm/ps3.h>
 
 static int ps3_ohci_hc_reset(struct usb_hcd *hcd)
@@ -75,7 +76,7 @@ static const struct hc_driver ps3_ohci_hc_driver = {
 #endif
 };
 
-static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
+static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
 {
        int result;
        struct usb_hcd *hcd;
@@ -87,13 +88,31 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
                goto fail_start;
        }
 
+       result = ps3_open_hv_device(dev);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+               result = -EPERM;
+               goto fail_open;
+       }
+
+       result = ps3_dma_region_create(dev->d_region);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
+                       "(%d)\n", __func__, __LINE__, result);
+               BUG_ON("check region type");
+               goto fail_dma_region;
+       }
+
        result = ps3_mmio_region_create(dev->m_region);
 
        if (result) {
                dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n",
                        __func__, __LINE__);
                result = -EPERM;
-               goto fail_mmio;
+               goto fail_mmio_region;
        }
 
        dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
@@ -122,6 +141,11 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
 
        hcd->rsrc_start = dev->m_region->lpar_addr;
        hcd->rsrc_len = dev->m_region->len;
+
+       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name))
+               dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n",
+                       __func__, __LINE__);
+
        hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len);
 
        if (!hcd->regs) {
@@ -155,34 +179,73 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
 fail_add_hcd:
        iounmap(hcd->regs);
 fail_ioremap:
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
 fail_create_hcd:
        ps3_io_irq_destroy(virq);
 fail_irq:
        ps3_free_mmio_region(dev->m_region);
-fail_mmio:
+fail_mmio_region:
+       ps3_dma_region_free(dev->d_region);
+fail_dma_region:
+       ps3_close_hv_device(dev);
+fail_open:
 fail_start:
        return result;
 }
 
-static int ps3_ohci_sb_remove (struct ps3_system_bus_device *dev)
+static int ps3_ohci_remove (struct ps3_system_bus_device *dev)
 {
+       unsigned int tmp;
        struct usb_hcd *hcd =
                (struct usb_hcd *)ps3_system_bus_get_driver_data(dev);
 
-       usb_put_hcd(hcd);
+       BUG_ON(!hcd);
+
+       dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs);
+       dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq);
+
+       tmp = hcd->irq;
+
+       usb_remove_hcd(hcd);
+
        ps3_system_bus_set_driver_data(dev, NULL);
 
+       BUG_ON(!hcd->regs);
+       iounmap(hcd->regs);
+
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+       usb_put_hcd(hcd);
+
+       ps3_io_irq_destroy(tmp);
+       ps3_free_mmio_region(dev->m_region);
+
+       ps3_dma_region_free(dev->d_region);
+       ps3_close_hv_device(dev);
+
        return 0;
 }
 
-MODULE_ALIAS("ps3-ohci");
+static int ps3_ohci_driver_register(struct ps3_system_bus_driver *drv)
+{
+       return firmware_has_feature(FW_FEATURE_PS3_LV1)
+               ? ps3_system_bus_driver_register(drv)
+               : 0;
+}
+
+static void ps3_ohci_driver_unregister(struct ps3_system_bus_driver *drv)
+{
+       if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+               ps3_system_bus_driver_unregister(drv);
+}
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_OHCI);
 
-static struct ps3_system_bus_driver ps3_ohci_sb_driver = {
+static struct ps3_system_bus_driver ps3_ohci_driver = {
+       .core.name = "ps3-ohci-driver",
+       .core.owner = THIS_MODULE,
        .match_id = PS3_MATCH_ID_OHCI,
-       .core = {
-               .name = "ps3-ohci-driver",
-       },
-       .probe = ps3_ohci_sb_probe,
-       .remove = ps3_ohci_sb_remove,
+       .probe = ps3_ohci_probe,
+       .remove = ps3_ohci_remove,
+       .shutdown = ps3_ohci_remove,
 };
index c2b5ecfe5e9fa8ca88b33a28b792dd15e3a43fb8..4ada43cf1387db28fefe811f18f5e02ac098666c 100644 (file)
@@ -397,8 +397,10 @@ struct ohci_hcd {
 #define        OHCI_QUIRK_BE_DESC      0x08                    /* BE descriptors */
 #define        OHCI_QUIRK_BE_MMIO      0x10                    /* BE registers */
 #define        OHCI_QUIRK_ZFMICRO      0x20                    /* Compaq ZFMicro chipset*/
+#define        OHCI_QUIRK_NEC          0x40                    /* lost interrupts */
        // there are also chip quirks/bugs in init logic
 
+       struct work_struct      nec_work;       /* Worker for NEC quirk */
 };
 
 /* convert between an hcd pointer and the corresponding ohci_hcd */
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
new file mode 100644 (file)
index 0000000..a7a7070
--- /dev/null
@@ -0,0 +1,2244 @@
+/*
+ * R8A66597 HCD (Host Controller Driver)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ * Portions Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
+ * Portions Copyright (C) 2004-2005 David Brownell
+ * Portions Copyright (C) 1999 Roman Weissgaerber
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "../core/hcd.h"
+#include "r8a66597.h"
+
+MODULE_DESCRIPTION("R8A66597 USB Host Controller Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+
+#define DRIVER_VERSION "29 May 2007"
+
+static const char hcd_name[] = "r8a66597_hcd";
+
+/* module parameters */
+static unsigned short clock = XTAL12;
+module_param(clock, ushort, 0644);
+MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=0)");
+static unsigned short vif = LDRV;
+module_param(vif, ushort, 0644);
+MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)");
+static unsigned short endian = 0;
+module_param(endian, ushort, 0644);
+MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)");
+static unsigned short irq_sense = INTL;
+module_param(irq_sense, ushort, 0644);
+MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0(default=32)");
+
+static void packet_write(struct r8a66597 *r8a66597, u16 pipenum);
+static int r8a66597_get_frame(struct usb_hcd *hcd);
+
+/* this function must be called with interrupt disabled */
+static void enable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
+                           unsigned long reg)
+{
+       u16 tmp;
+
+       tmp = r8a66597_read(r8a66597, INTENB0);
+       r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0);
+       r8a66597_bset(r8a66597, 1 << pipenum, reg);
+       r8a66597_write(r8a66597, tmp, INTENB0);
+}
+
+/* this function must be called with interrupt disabled */
+static void disable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
+                            unsigned long reg)
+{
+       u16 tmp;
+
+       tmp = r8a66597_read(r8a66597, INTENB0);
+       r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0);
+       r8a66597_bclr(r8a66597, 1 << pipenum, reg);
+       r8a66597_write(r8a66597, tmp, INTENB0);
+}
+
+static void set_devadd_reg(struct r8a66597 *r8a66597, u8 r8a66597_address,
+                          u16 usbspd, u8 upphub, u8 hubport, int port)
+{
+       u16 val;
+       unsigned long devadd_reg = get_devadd_addr(r8a66597_address);
+
+       val = (upphub << 11) | (hubport << 8) | (usbspd << 6) | (port & 0x0001);
+       r8a66597_write(r8a66597, val, devadd_reg);
+}
+
+static int enable_controller(struct r8a66597 *r8a66597)
+{
+       u16 tmp;
+       int i = 0;
+
+       do {
+               r8a66597_write(r8a66597, USBE, SYSCFG0);
+               tmp = r8a66597_read(r8a66597, SYSCFG0);
+               if (i++ > 1000) {
+                       err("register access fail.");
+                       return -ENXIO;
+               }
+       } while ((tmp & USBE) != USBE);
+       r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+       r8a66597_mdfy(r8a66597, clock, XTAL, SYSCFG0);
+
+       i = 0;
+       r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+       do {
+               msleep(1);
+               tmp = r8a66597_read(r8a66597, SYSCFG0);
+               if (i++ > 500) {
+                       err("register access fail.");
+                       return -ENXIO;
+               }
+       } while ((tmp & SCKE) != SCKE);
+
+       r8a66597_bset(r8a66597, DCFM | DRPD, SYSCFG0);
+       r8a66597_bset(r8a66597, DRPD, SYSCFG1);
+
+       r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
+       r8a66597_bset(r8a66597, HSE, SYSCFG0);
+       r8a66597_bset(r8a66597, HSE, SYSCFG1);
+       r8a66597_bset(r8a66597, USBE, SYSCFG0);
+
+       r8a66597_bset(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0);
+       r8a66597_bset(r8a66597, irq_sense & INTL, SOFCFG);
+       r8a66597_bset(r8a66597, BRDY0, BRDYENB);
+       r8a66597_bset(r8a66597, BEMP0, BEMPENB);
+
+       r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA0CFG);
+       r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA1CFG);
+
+       r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL);
+       r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL);
+       r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL);
+
+       r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
+
+       r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1);
+       r8a66597_bclr(r8a66597, DTCHE, INTENB1);
+       r8a66597_bset(r8a66597, ATTCHE, INTENB1);
+       r8a66597_bclr(r8a66597, DTCHE, INTENB2);
+       r8a66597_bset(r8a66597, ATTCHE, INTENB2);
+
+       return 0;
+}
+
+static void disable_controller(struct r8a66597 *r8a66597)
+{
+       u16 tmp;
+
+       r8a66597_write(r8a66597, 0, INTENB0);
+       r8a66597_write(r8a66597, 0, INTENB1);
+       r8a66597_write(r8a66597, 0, INTENB2);
+       r8a66597_write(r8a66597, 0, INTSTS0);
+       r8a66597_write(r8a66597, 0, INTSTS1);
+       r8a66597_write(r8a66597, 0, INTSTS2);
+
+       r8a66597_port_power(r8a66597, 0, 0);
+       r8a66597_port_power(r8a66597, 1, 0);
+
+       do {
+               tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
+               udelay(640);
+       } while (tmp == EDGESTS);
+
+       r8a66597_bclr(r8a66597, DCFM | DRPD, SYSCFG0);
+       r8a66597_bclr(r8a66597, DRPD, SYSCFG1);
+       r8a66597_bclr(r8a66597, HSE, SYSCFG0);
+       r8a66597_bclr(r8a66597, HSE, SYSCFG1);
+
+       r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+       udelay(1);
+       r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+       r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+       r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+}
+
+static int get_parent_r8a66597_address(struct r8a66597 *r8a66597,
+                                      struct usb_device *udev)
+{
+       struct r8a66597_device *dev;
+
+       if (udev->parent && udev->parent->devnum != 1)
+               udev = udev->parent;
+
+       dev = dev_get_drvdata(&udev->dev);
+       if (dev)
+               return dev->address;
+       else
+               return 0;
+}
+
+static int is_child_device(char *devpath)
+{
+       return (devpath[2] ? 1 : 0);
+}
+
+static int is_hub_limit(char *devpath)
+{
+       return ((strlen(devpath) >= 4) ? 1 : 0);
+}
+
+static void get_port_number(char *devpath, u16 *root_port, u16 *hub_port)
+{
+       if (root_port) {
+               *root_port = (devpath[0] & 0x0F) - 1;
+               if (*root_port >= R8A66597_MAX_ROOT_HUB)
+                       err("illegal root port number");
+       }
+       if (hub_port)
+               *hub_port = devpath[2] & 0x0F;
+}
+
+static u16 get_r8a66597_usb_speed(enum usb_device_speed speed)
+{
+       u16 usbspd = 0;
+
+       switch (speed) {
+       case USB_SPEED_LOW:
+               usbspd = LSMODE;
+               break;
+       case USB_SPEED_FULL:
+               usbspd = FSMODE;
+               break;
+       case USB_SPEED_HIGH:
+               usbspd = HSMODE;
+               break;
+       default:
+               err("unknown speed");
+               break;
+       }
+
+       return usbspd;
+}
+
+static void set_child_connect_map(struct r8a66597 *r8a66597, int address)
+{
+       int idx;
+
+       idx = address / 32;
+       r8a66597->child_connect_map[idx] |= 1 << (address % 32);
+}
+
+static void put_child_connect_map(struct r8a66597 *r8a66597, int address)
+{
+       int idx;
+
+       idx = address / 32;
+       r8a66597->child_connect_map[idx] &= ~(1 << (address % 32));
+}
+
+static void set_pipe_reg_addr(struct r8a66597_pipe *pipe, u8 dma_ch)
+{
+       u16 pipenum = pipe->info.pipenum;
+       unsigned long fifoaddr[] = {D0FIFO, D1FIFO, CFIFO};
+       unsigned long fifosel[] = {D0FIFOSEL, D1FIFOSEL, CFIFOSEL};
+       unsigned long fifoctr[] = {D0FIFOCTR, D1FIFOCTR, CFIFOCTR};
+
+       if (dma_ch > R8A66597_PIPE_NO_DMA)      /* dma fifo not use? */
+               dma_ch = R8A66597_PIPE_NO_DMA;
+
+       pipe->fifoaddr = fifoaddr[dma_ch];
+       pipe->fifosel = fifosel[dma_ch];
+       pipe->fifoctr = fifoctr[dma_ch];
+
+       if (pipenum == 0)
+               pipe->pipectr = DCPCTR;
+       else
+               pipe->pipectr = get_pipectr_addr(pipenum);
+
+       if (check_bulk_or_isoc(pipenum)) {
+               pipe->pipetre = get_pipetre_addr(pipenum);
+               pipe->pipetrn = get_pipetrn_addr(pipenum);
+       } else {
+               pipe->pipetre = 0;
+               pipe->pipetrn = 0;
+       }
+}
+
+static struct r8a66597_device *
+get_urb_to_r8a66597_dev(struct r8a66597 *r8a66597, struct urb *urb)
+{
+       if (usb_pipedevice(urb->pipe) == 0)
+               return &r8a66597->device0;
+
+       return dev_get_drvdata(&urb->dev->dev);
+}
+
+static int make_r8a66597_device(struct r8a66597 *r8a66597,
+                               struct urb *urb, u8 addr)
+{
+       struct r8a66597_device *dev;
+       int usb_address = urb->setup_packet[2]; /* urb->pipe is address 0 */
+
+       dev = kzalloc(sizeof(struct r8a66597_device), GFP_KERNEL);
+       if (dev == NULL)
+               return -ENOMEM;
+
+       dev_set_drvdata(&urb->dev->dev, dev);
+       dev->udev = urb->dev;
+       dev->address = addr;
+       dev->usb_address = usb_address;
+       dev->state = USB_STATE_ADDRESS;
+       dev->ep_in_toggle = 0;
+       dev->ep_out_toggle = 0;
+       INIT_LIST_HEAD(&dev->device_list);
+       list_add_tail(&dev->device_list, &r8a66597->child_device);
+
+       get_port_number(urb->dev->devpath, &dev->root_port, &dev->hub_port);
+       if (!is_child_device(urb->dev->devpath))
+               r8a66597->root_hub[dev->root_port].dev = dev;
+
+       set_devadd_reg(r8a66597, dev->address,
+                      get_r8a66597_usb_speed(urb->dev->speed),
+                      get_parent_r8a66597_address(r8a66597, urb->dev),
+                      dev->hub_port, dev->root_port);
+
+       return 0;
+}
+
+/* this function must be called with interrupt disabled */
+static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb)
+{
+       u8 addr;        /* R8A66597's address */
+       struct r8a66597_device *dev;
+
+       if (is_hub_limit(urb->dev->devpath)) {
+               err("Externel hub limit reached.");
+               return 0;
+       }
+
+       dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+       if (dev && dev->state >= USB_STATE_ADDRESS)
+               return dev->address;
+
+       for (addr = 1; addr <= R8A66597_MAX_DEVICE; addr++) {
+               if (r8a66597->address_map & (1 << addr))
+                       continue;
+
+               dbg("alloc_address: r8a66597_addr=%d", addr);
+               r8a66597->address_map |= 1 << addr;
+
+               if (make_r8a66597_device(r8a66597, urb, addr) < 0)
+                       return 0;
+
+               return addr;
+       }
+
+       err("cannot communicate with a USB device more than 10.(%x)",
+           r8a66597->address_map);
+
+       return 0;
+}
+
+/* this function must be called with interrupt disabled */
+static void free_usb_address(struct r8a66597 *r8a66597,
+                            struct r8a66597_device *dev)
+{
+       int port;
+
+       if (!dev)
+               return;
+
+       dbg("free_addr: addr=%d", dev->address);
+
+       dev->state = USB_STATE_DEFAULT;
+       r8a66597->address_map &= ~(1 << dev->address);
+       dev->address = 0;
+       dev_set_drvdata(&dev->udev->dev, NULL);
+       list_del(&dev->device_list);
+       kfree(dev);
+
+       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+               if (r8a66597->root_hub[port].dev == dev) {
+                       r8a66597->root_hub[port].dev = NULL;
+                       break;
+               }
+       }
+}
+
+static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg,
+                             u16 mask, u16 loop)
+{
+       u16 tmp;
+       int i = 0;
+
+       do {
+               tmp = r8a66597_read(r8a66597, reg);
+               if (i++ > 1000000) {
+                       err("register%lx, loop %x is timeout", reg, loop);
+                       break;
+               }
+               ndelay(1);
+       } while ((tmp & mask) != loop);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_start(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe)
+{
+       u16 tmp;
+
+       tmp = r8a66597_read(r8a66597, pipe->pipectr) & PID;
+       if ((pipe->info.pipenum != 0) & ((tmp & PID_STALL) != 0)) /* stall? */
+               r8a66597_mdfy(r8a66597, PID_NAK, PID, pipe->pipectr);
+       r8a66597_mdfy(r8a66597, PID_BUF, PID, pipe->pipectr);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_stop(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe)
+{
+       u16 tmp;
+
+       tmp = r8a66597_read(r8a66597, pipe->pipectr) & PID;
+       if ((tmp & PID_STALL11) != PID_STALL11) /* force stall? */
+               r8a66597_mdfy(r8a66597, PID_STALL, PID, pipe->pipectr);
+       r8a66597_mdfy(r8a66597, PID_NAK, PID, pipe->pipectr);
+       r8a66597_reg_wait(r8a66597, pipe->pipectr, PBUSY, 0);
+}
+
+/* this function must be called with interrupt disabled */
+static void clear_all_buffer(struct r8a66597 *r8a66597,
+                            struct r8a66597_pipe *pipe)
+{
+       u16 tmp;
+
+       if (!pipe || pipe->info.pipenum == 0)
+               return;
+
+       pipe_stop(r8a66597, pipe);
+       r8a66597_bset(r8a66597, ACLRM, pipe->pipectr);
+       tmp = r8a66597_read(r8a66597, pipe->pipectr);
+       tmp = r8a66597_read(r8a66597, pipe->pipectr);
+       tmp = r8a66597_read(r8a66597, pipe->pipectr);
+       r8a66597_bclr(r8a66597, ACLRM, pipe->pipectr);
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_pipe_toggle(struct r8a66597 *r8a66597,
+                                struct r8a66597_pipe *pipe, int toggle)
+{
+       if (toggle)
+               r8a66597_bset(r8a66597, SQSET, pipe->pipectr);
+       else
+               r8a66597_bset(r8a66597, SQCLR, pipe->pipectr);
+}
+
+/* this function must be called with interrupt disabled */
+static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
+       r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
+}
+
+/* this function must be called with interrupt disabled */
+static inline void fifo_change_from_pipe(struct r8a66597 *r8a66597,
+                                        struct r8a66597_pipe *pipe)
+{
+       cfifo_change(r8a66597, 0);
+       r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D0FIFOSEL);
+       r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D1FIFOSEL);
+
+       r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, MBW | CURPIPE,
+                     pipe->fifosel);
+       r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, pipe->info.pipenum);
+}
+
+static u16 r8a66597_get_pipenum(struct urb *urb, struct usb_host_endpoint *hep)
+{
+       struct r8a66597_pipe *pipe = hep->hcpriv;
+
+       if (usb_pipeendpoint(urb->pipe) == 0)
+               return 0;
+       else
+               return pipe->info.pipenum;
+}
+
+static u16 get_urb_to_r8a66597_addr(struct r8a66597 *r8a66597, struct urb *urb)
+{
+       struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+
+       return (usb_pipedevice(urb->pipe) == 0) ? 0 : dev->address;
+}
+
+static unsigned short *get_toggle_pointer(struct r8a66597_device *dev,
+                                         int urb_pipe)
+{
+       if (!dev)
+               return NULL;
+
+       return usb_pipein(urb_pipe) ? &dev->ep_in_toggle : &dev->ep_out_toggle;
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_toggle_set(struct r8a66597 *r8a66597,
+                           struct r8a66597_pipe *pipe,
+                           struct urb *urb, int set)
+{
+       struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+       unsigned char endpoint = usb_pipeendpoint(urb->pipe);
+       unsigned short *toggle = get_toggle_pointer(dev, urb->pipe);
+
+       if (!toggle)
+               return;
+
+       if (set)
+               *toggle |= 1 << endpoint;
+       else
+               *toggle &= ~(1 << endpoint);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_toggle_save(struct r8a66597 *r8a66597,
+                            struct r8a66597_pipe *pipe,
+                            struct urb *urb)
+{
+       if (r8a66597_read(r8a66597, pipe->pipectr) & SQMON)
+               pipe_toggle_set(r8a66597, pipe, urb, 1);
+       else
+               pipe_toggle_set(r8a66597, pipe, urb, 0);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_toggle_restore(struct r8a66597 *r8a66597,
+                               struct r8a66597_pipe *pipe,
+                               struct urb *urb)
+{
+       struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+       unsigned char endpoint = usb_pipeendpoint(urb->pipe);
+       unsigned short *toggle = get_toggle_pointer(dev, urb->pipe);
+
+       if (!toggle)
+               return;
+
+       r8a66597_pipe_toggle(r8a66597, pipe, *toggle & (1 << endpoint));
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_buffer_setting(struct r8a66597 *r8a66597,
+                               struct r8a66597_pipe_info *info)
+{
+       u16 val = 0;
+
+       if (info->pipenum == 0)
+               return;
+
+       r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(info->pipenum));
+       r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(info->pipenum));
+       r8a66597_write(r8a66597, info->pipenum, PIPESEL);
+       if (!info->dir_in)
+               val |= R8A66597_DIR;
+       if (info->type == R8A66597_BULK && info->dir_in)
+               val |= R8A66597_DBLB | R8A66597_SHTNAK;
+       val |= info->type | info->epnum;
+       r8a66597_write(r8a66597, val, PIPECFG);
+
+       r8a66597_write(r8a66597, (info->buf_bsize << 10) | (info->bufnum),
+                      PIPEBUF);
+       r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket,
+                      PIPEMAXP);
+       if (info->interval)
+               info->interval--;
+       r8a66597_write(r8a66597, info->interval, PIPEPERI);
+}
+
+
+
+/* this function must be called with interrupt disabled */
+static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+{
+       struct r8a66597_pipe_info *info;
+       struct urb *urb = td->urb;
+
+       if (td->pipenum > 0) {
+               info = &td->pipe->info;
+               cfifo_change(r8a66597, 0);
+               pipe_buffer_setting(r8a66597, info);
+
+               if (!usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+                                  usb_pipeout(urb->pipe)) &&
+                   !usb_pipecontrol(urb->pipe)) {
+                       r8a66597_pipe_toggle(r8a66597, td->pipe, 0);
+                       pipe_toggle_set(r8a66597, td->pipe, urb, 0);
+                       clear_all_buffer(r8a66597, td->pipe);
+                       usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+                                     usb_pipeout(urb->pipe), 1);
+               }
+               pipe_toggle_restore(r8a66597, td->pipe, urb);
+       }
+}
+
+/* this function must be called with interrupt disabled */
+static u16 get_empty_pipenum(struct r8a66597 *r8a66597,
+                            struct usb_endpoint_descriptor *ep)
+{
+       u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min;
+
+       memset(array, 0, sizeof(array));
+        switch(ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+        case USB_ENDPOINT_XFER_BULK:
+               if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+                       array[i++] = 4;
+               else {
+                       array[i++] = 3;
+                       array[i++] = 5;
+               }
+                break;
+        case USB_ENDPOINT_XFER_INT:
+               if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+                       array[i++] = 6;
+                       array[i++] = 7;
+                       array[i++] = 8;
+               } else
+                       array[i++] = 9;
+                break;
+        case USB_ENDPOINT_XFER_ISOC:
+               if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+                       array[i++] = 2;
+               else
+                       array[i++] = 1;
+                break;
+        default:
+                err("Illegal type");
+                return 0;
+        }
+
+       i = 1;
+       min = array[0];
+       while (array[i] != 0) {
+               if (r8a66597->pipe_cnt[min] > r8a66597->pipe_cnt[array[i]])
+                       min = array[i];
+               i++;
+       }
+
+       return min;
+}
+
+static u16 get_r8a66597_type(__u8 type)
+{
+       u16 r8a66597_type;
+
+       switch(type) {
+       case USB_ENDPOINT_XFER_BULK:
+               r8a66597_type = R8A66597_BULK;
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               r8a66597_type = R8A66597_INT;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               r8a66597_type = R8A66597_ISO;
+               break;
+       default:
+               err("Illegal type");
+               r8a66597_type = 0x0000;
+               break;
+       }
+
+       return r8a66597_type;
+}
+
+static u16 get_bufnum(u16 pipenum)
+{
+       u16 bufnum = 0;
+
+       if (pipenum == 0)
+               bufnum = 0;
+       else if (check_bulk_or_isoc(pipenum))
+               bufnum = 8 + (pipenum - 1) * R8A66597_BUF_BSIZE*2;
+       else if (check_interrupt(pipenum))
+               bufnum = 4 + (pipenum - 6);
+       else
+               err("Illegal pipenum (%d)", pipenum);
+
+       return bufnum;
+}
+
+static u16 get_buf_bsize(u16 pipenum)
+{
+       u16 buf_bsize = 0;
+
+       if (pipenum == 0)
+               buf_bsize = 3;
+       else if (check_bulk_or_isoc(pipenum))
+               buf_bsize = R8A66597_BUF_BSIZE - 1;
+       else if (check_interrupt(pipenum))
+               buf_bsize = 0;
+       else
+               err("Illegal pipenum (%d)", pipenum);
+
+       return buf_bsize;
+}
+
+/* this function must be called with interrupt disabled */
+static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
+                                    struct r8a66597_device *dev,
+                                    struct r8a66597_pipe *pipe,
+                                    struct urb *urb)
+{
+       int i;
+       struct r8a66597_pipe_info *info = &pipe->info;
+
+       if ((pipe->info.pipenum != 0) && (info->type != R8A66597_INT)) {
+               for (i = 0; i < R8A66597_MAX_DMA_CHANNEL; i++) {
+                       if ((r8a66597->dma_map & (1 << i)) != 0)
+                               continue;
+
+                       info("address %d, EndpointAddress 0x%02x use DMA FIFO",
+                            usb_pipedevice(urb->pipe),
+                            info->dir_in ? USB_ENDPOINT_DIR_MASK + info->epnum
+                                           : info->epnum);
+
+                       r8a66597->dma_map |= 1 << i;
+                       dev->dma_map |= 1 << i;
+                       set_pipe_reg_addr(pipe, i);
+
+                       cfifo_change(r8a66597, 0);
+                       r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum,
+                                     MBW | CURPIPE, pipe->fifosel);
+
+                       r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE,
+                                         pipe->info.pipenum);
+                       r8a66597_bset(r8a66597, BCLR, pipe->fifoctr);
+                       break;
+               }
+       }
+}
+
+/* this function must be called with interrupt disabled */
+static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb,
+                                struct usb_host_endpoint *hep,
+                                struct r8a66597_pipe_info *info)
+{
+       struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+       struct r8a66597_pipe *pipe = hep->hcpriv;
+
+       dbg("enable_pipe:");
+
+       pipe->info = *info;
+       set_pipe_reg_addr(pipe, R8A66597_PIPE_NO_DMA);
+       r8a66597->pipe_cnt[pipe->info.pipenum]++;
+       dev->pipe_cnt[pipe->info.pipenum]++;
+
+       enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb);
+}
+
+/* this function must be called with interrupt disabled */
+static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
+{
+       struct r8a66597_td *td, *next;
+       struct urb *urb;
+       struct list_head *list = &r8a66597->pipe_queue[pipenum];
+
+       if (list_empty(list))
+               return;
+
+       list_for_each_entry_safe(td, next, list, queue) {
+               if (!td)
+                       continue;
+               if (td->address != address)
+                       continue;
+
+               urb = td->urb;
+               list_del(&td->queue);
+               kfree(td);
+
+               if (urb) {
+                       urb->status = -ENODEV;
+                       urb->hcpriv = NULL;
+                       spin_unlock(&r8a66597->lock);
+                       usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb);
+                       spin_lock(&r8a66597->lock);
+               }
+               break;
+       }
+}
+
+/* this function must be called with interrupt disabled */
+static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597,
+                                     struct r8a66597_device *dev)
+{
+       int check_ep0 = 0;
+       u16 pipenum;
+
+       if (!dev)
+               return;
+
+       for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+               if (!dev->pipe_cnt[pipenum])
+                       continue;
+
+               if (!check_ep0) {
+                       check_ep0 = 1;
+                       force_dequeue(r8a66597, 0, dev->address);
+               }
+
+               r8a66597->pipe_cnt[pipenum] -= dev->pipe_cnt[pipenum];
+               dev->pipe_cnt[pipenum] = 0;
+               force_dequeue(r8a66597, pipenum, dev->address);
+       }
+
+       dbg("disable_pipe");
+
+       r8a66597->dma_map &= ~(dev->dma_map);
+       dev->dma_map = 0;
+}
+
+/* this function must be called with interrupt disabled */
+static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
+                          struct usb_host_endpoint *hep,
+                          struct usb_endpoint_descriptor *ep)
+{
+       struct r8a66597_pipe_info info;
+
+       info.pipenum = get_empty_pipenum(r8a66597, ep);
+       info.address = get_urb_to_r8a66597_addr(r8a66597, urb);
+       info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+       info.maxpacket = ep->wMaxPacketSize;
+       info.type = get_r8a66597_type(ep->bmAttributes
+                                     & USB_ENDPOINT_XFERTYPE_MASK);
+       info.bufnum = get_bufnum(info.pipenum);
+       info.buf_bsize = get_buf_bsize(info.pipenum);
+       info.interval = ep->bInterval;
+       if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+               info.dir_in = 1;
+       else
+               info.dir_in = 0;
+
+       enable_r8a66597_pipe(r8a66597, urb, hep, &info);
+}
+
+static void init_pipe_config(struct r8a66597 *r8a66597, struct urb *urb)
+{
+       struct r8a66597_device *dev;
+
+       dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+       dev->state = USB_STATE_CONFIGURED;
+}
+
+static void pipe_irq_enable(struct r8a66597 *r8a66597, struct urb *urb,
+                           u16 pipenum)
+{
+       if (pipenum == 0 && usb_pipeout(urb->pipe))
+               enable_irq_empty(r8a66597, pipenum);
+       else
+               enable_irq_ready(r8a66597, pipenum);
+
+       if (!usb_pipeisoc(urb->pipe))
+               enable_irq_nrdy(r8a66597, pipenum);
+}
+
+static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       disable_irq_ready(r8a66597, pipenum);
+       disable_irq_nrdy(r8a66597, pipenum);
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_usb_preconnect(struct r8a66597 *r8a66597, int port)
+{
+       r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
+                                        | (1 << USB_PORT_FEAT_C_CONNECTION);
+       r8a66597_write(r8a66597, (u16)~DTCH, get_intsts_reg(port));
+       r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)
+{
+       u16 speed = get_rh_usb_speed(r8a66597, port);
+       struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
+       if (speed == HSMODE)
+               rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED);
+       else if (speed == LSMODE)
+               rh->port |= (1 << USB_PORT_FEAT_LOWSPEED);
+
+       rh->port &= ~(1 << USB_PORT_FEAT_RESET);
+       rh->port |= 1 << USB_PORT_FEAT_ENABLE;
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port)
+{
+       struct r8a66597_device *dev = r8a66597->root_hub[port].dev;
+
+       r8a66597->root_hub[port].port &= ~(1 << USB_PORT_FEAT_CONNECTION);
+       r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_C_CONNECTION);
+
+       disable_r8a66597_pipe_all(r8a66597, dev);
+       free_usb_address(r8a66597, dev);
+
+       r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_setup_packet(struct r8a66597 *r8a66597,
+                                struct r8a66597_td *td)
+{
+       int i;
+       u16 *p = (u16 *)td->urb->setup_packet;
+       unsigned long setup_addr = USBREQ;
+
+       r8a66597_write(r8a66597, make_devsel(td->address) | td->maxpacket,
+                      DCPMAXP);
+       r8a66597_write(r8a66597, (u16)~(SIGN | SACK), INTSTS1);
+
+       for (i = 0; i < 4; i++) {
+               r8a66597_write(r8a66597, p[i], setup_addr);
+               setup_addr += 2;
+       }
+       r8a66597_write(r8a66597, SUREQ, DCPCTR);
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_packet_read(struct r8a66597 *r8a66597,
+                               struct r8a66597_td *td)
+{
+       struct urb *urb = td->urb;
+
+       if (usb_pipecontrol(urb->pipe)) {
+               r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+               r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+               r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+               if (urb->actual_length == 0) {
+                       r8a66597_pipe_toggle(r8a66597, td->pipe, 1);
+                       r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+               }
+               pipe_irq_disable(r8a66597, td->pipenum);
+               pipe_start(r8a66597, td->pipe);
+               pipe_irq_enable(r8a66597, urb, td->pipenum);
+       } else {
+               if (urb->actual_length == 0) {
+                       pipe_irq_disable(r8a66597, td->pipenum);
+                       pipe_setting(r8a66597, td);
+                       pipe_stop(r8a66597, td->pipe);
+                       r8a66597_write(r8a66597, (u16)~(1 << td->pipenum),
+                                      BRDYSTS);
+
+                       if (td->pipe->pipetre) {
+                               r8a66597_write(r8a66597, TRCLR,
+                                               td->pipe->pipetre);
+                               r8a66597_write(r8a66597,
+                                              (urb->transfer_buffer_length
+                                              + td->maxpacket - 1)
+                                              / td->maxpacket,
+                                              td->pipe->pipetrn);
+                               r8a66597_bset(r8a66597, TRENB,
+                                             td->pipe->pipetre);
+                       }
+
+                       pipe_start(r8a66597, td->pipe);
+                       pipe_irq_enable(r8a66597, urb, td->pipenum);
+               }
+       }
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_packet_write(struct r8a66597 *r8a66597,
+                                struct r8a66597_td *td)
+{
+       u16 tmp;
+       struct urb *urb = td->urb;
+
+       if (usb_pipecontrol(urb->pipe)) {
+               pipe_stop(r8a66597, td->pipe);
+               r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
+               r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
+               r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+               if (urb->actual_length == 0) {
+                       r8a66597_pipe_toggle(r8a66597, td->pipe, 1);
+                       r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+               }
+       } else {
+               if (urb->actual_length == 0)
+                       pipe_setting(r8a66597, td);
+               if (td->pipe->pipetre)
+                       r8a66597_bclr(r8a66597, TRENB, td->pipe->pipetre);
+       }
+       r8a66597_write(r8a66597, (u16)~(1 << td->pipenum), BRDYSTS);
+
+       fifo_change_from_pipe(r8a66597, td->pipe);
+       tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
+       if (unlikely((tmp & FRDY) == 0))
+               pipe_irq_enable(r8a66597, urb, td->pipenum);
+       else
+               packet_write(r8a66597, td->pipenum);
+       pipe_start(r8a66597, td->pipe);
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_status_packet(struct r8a66597 *r8a66597,
+                                 struct r8a66597_td *td)
+{
+       struct urb *urb = td->urb;
+
+       r8a66597_pipe_toggle(r8a66597, td->pipe, 1);
+
+       if (urb->setup_packet[0] & USB_ENDPOINT_DIR_MASK) {
+               r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
+               r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
+               r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+               r8a66597_write(r8a66597, BVAL | BCLR, CFIFOCTR);
+               r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS);
+               enable_irq_empty(r8a66597, 0);
+       } else {
+               r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+               r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+               r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+               r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+               r8a66597_write(r8a66597, (u16)~BRDY0, BRDYSTS);
+               r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS);
+               enable_irq_ready(r8a66597, 0);
+       }
+       enable_irq_nrdy(r8a66597, 0);
+       pipe_start(r8a66597, td->pipe);
+}
+
+/* this function must be called with interrupt disabled */
+static int start_transfer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+{
+       BUG_ON(!td);
+
+       switch (td->type) {
+       case USB_PID_SETUP:
+               if (td->urb->setup_packet[1] == USB_REQ_SET_ADDRESS) {
+                       td->set_address = 1;
+                       td->urb->setup_packet[2] = alloc_usb_address(r8a66597,
+                                                                    td->urb);
+                       if (td->urb->setup_packet[2] == 0)
+                               return -EPIPE;
+               }
+               prepare_setup_packet(r8a66597, td);
+               break;
+       case USB_PID_IN:
+               prepare_packet_read(r8a66597, td);
+               break;
+       case USB_PID_OUT:
+               prepare_packet_write(r8a66597, td);
+               break;
+       case USB_PID_ACK:
+               prepare_status_packet(r8a66597, td);
+               break;
+       default:
+               err("invalid type.");
+               break;
+       }
+
+       return 0;
+}
+
+static int check_transfer_finish(struct r8a66597_td *td, struct urb *urb)
+{
+       if (usb_pipeisoc(urb->pipe)) {
+               if (urb->number_of_packets == td->iso_cnt)
+                       return 1;
+       }
+
+       /* control or bulk or interrupt */
+       if ((urb->transfer_buffer_length <= urb->actual_length) ||
+           (td->short_packet) || (td->zero_packet))
+               return 1;
+
+       return 0;
+}
+
+/* this function must be called with interrupt disabled */
+static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+{
+       unsigned long time;
+
+       BUG_ON(!td);
+
+       if (!list_empty(&r8a66597->pipe_queue[td->pipenum]) &&
+           !usb_pipecontrol(td->urb->pipe) && usb_pipein(td->urb->pipe)) {
+               r8a66597->timeout_map |= 1 << td->pipenum;
+               switch (usb_pipetype(td->urb->pipe)) {
+               case PIPE_INTERRUPT:
+               case PIPE_ISOCHRONOUS:
+                       time = 30;
+                       break;
+               default:
+                       time = 300;
+                       break;
+               }
+
+               mod_timer(&r8a66597->td_timer[td->pipenum],
+                         jiffies + msecs_to_jiffies(time));
+       }
+}
+
+/* this function must be called with interrupt disabled */
+static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td,
+                u16 pipenum, struct urb *urb)
+{
+       int restart = 0;
+       struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597);
+
+       r8a66597->timeout_map &= ~(1 << pipenum);
+
+       if (likely(td)) {
+               if (td->set_address && urb->status != 0)
+                       r8a66597->address_map &= ~(1 << urb->setup_packet[2]);
+
+               pipe_toggle_save(r8a66597, td->pipe, urb);
+               list_del(&td->queue);
+               kfree(td);
+       }
+
+       if (!list_empty(&r8a66597->pipe_queue[pipenum]))
+               restart = 1;
+
+       if (likely(urb)) {
+               if (usb_pipeisoc(urb->pipe))
+                       urb->start_frame = r8a66597_get_frame(hcd);
+
+               urb->hcpriv = NULL;
+               spin_unlock(&r8a66597->lock);
+               usb_hcd_giveback_urb(hcd, urb);
+               spin_lock(&r8a66597->lock);
+       }
+
+       if (restart) {
+               td = r8a66597_get_td(r8a66597, pipenum);
+               if (unlikely(!td))
+                       return;
+
+               start_transfer(r8a66597, td);
+               set_td_timer(r8a66597, td);
+       }
+}
+
+/* this function must be called with interrupt disabled */
+static void finish_request(struct r8a66597 *r8a66597, struct r8a66597_td *td,
+                          u16 pipenum, struct urb *urb)
+__releases(r8a66597->lock) __acquires(r8a66597->lock)
+{
+       done(r8a66597, td, pipenum, urb);
+}
+
+static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       u16 tmp;
+       int rcv_len, bufsize, urb_len, size;
+       u16 *buf;
+       struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum);
+       struct urb *urb;
+       int finish = 0;
+
+       if (unlikely(!td))
+               return;
+       urb = td->urb;
+
+       fifo_change_from_pipe(r8a66597, td->pipe);
+       tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
+       if (unlikely((tmp & FRDY) == 0)) {
+               urb->status = -EPIPE;
+               pipe_stop(r8a66597, td->pipe);
+               pipe_irq_disable(r8a66597, pipenum);
+               err("in fifo not ready (%d)", pipenum);
+               finish_request(r8a66597, td, pipenum, td->urb);
+               return;
+       }
+
+       /* prepare parameters */
+       rcv_len = tmp & DTLN;
+       bufsize = td->maxpacket;
+       if (usb_pipeisoc(urb->pipe)) {
+               buf = (u16 *)(urb->transfer_buffer +
+                               urb->iso_frame_desc[td->iso_cnt].offset);
+               urb_len = urb->iso_frame_desc[td->iso_cnt].length;
+       } else {
+               buf = (void *)urb->transfer_buffer + urb->actual_length;
+               urb_len = urb->transfer_buffer_length - urb->actual_length;
+       }
+       if (rcv_len < bufsize)
+               size = min(rcv_len, urb_len);
+       else
+               size = min(bufsize, urb_len);
+
+       /* update parameters */
+       urb->actual_length += size;
+       if (rcv_len == 0)
+               td->zero_packet = 1;
+       if ((size % td->maxpacket) > 0) {
+               td->short_packet = 1;
+               if (urb->transfer_buffer_length != urb->actual_length &&
+                   urb->transfer_flags & URB_SHORT_NOT_OK)
+                       td->urb->status = -EREMOTEIO;
+       }
+       if (usb_pipeisoc(urb->pipe)) {
+               urb->iso_frame_desc[td->iso_cnt].actual_length = size;
+               urb->iso_frame_desc[td->iso_cnt].status = 0;
+               td->iso_cnt++;
+       }
+
+       /* check transfer finish */
+       if (check_transfer_finish(td, urb)) {
+               pipe_stop(r8a66597, td->pipe);
+               pipe_irq_disable(r8a66597, pipenum);
+               finish = 1;
+       }
+
+       /* read fifo */
+       if (urb->transfer_buffer) {
+               if (size == 0)
+                       r8a66597_write(r8a66597, BCLR, td->pipe->fifoctr);
+               else
+                       r8a66597_read_fifo(r8a66597, td->pipe->fifoaddr,
+                                          buf, size);
+       }
+
+       if (finish && pipenum != 0) {
+               if (td->urb->status == -EINPROGRESS)
+                       td->urb->status = 0;
+               finish_request(r8a66597, td, pipenum, urb);
+       }
+}
+
+static void packet_write(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       u16 tmp;
+       int bufsize, size;
+       u16 *buf;
+       struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum);
+       struct urb *urb;
+
+       if (unlikely(!td))
+               return;
+       urb = td->urb;
+
+       fifo_change_from_pipe(r8a66597, td->pipe);
+       tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
+       if (unlikely((tmp & FRDY) == 0)) {
+               urb->status = -EPIPE;
+               pipe_stop(r8a66597, td->pipe);
+               pipe_irq_disable(r8a66597, pipenum);
+               err("out write fifo not ready. (%d)", pipenum);
+               finish_request(r8a66597, td, pipenum, td->urb);
+               return;
+       }
+
+       /* prepare parameters */
+       bufsize = td->maxpacket;
+       if (usb_pipeisoc(urb->pipe)) {
+               buf = (u16 *)(urb->transfer_buffer +
+                               urb->iso_frame_desc[td->iso_cnt].offset);
+               size = min(bufsize,
+                          (int)urb->iso_frame_desc[td->iso_cnt].length);
+       } else {
+               buf = (u16 *)(urb->transfer_buffer + urb->actual_length);
+               size = min((int)bufsize,
+                          urb->transfer_buffer_length - urb->actual_length);
+       }
+
+       /* write fifo */
+       if (pipenum > 0)
+               r8a66597_write(r8a66597, (u16)~(1 << pipenum), BEMPSTS);
+       if (urb->transfer_buffer) {
+               r8a66597_write_fifo(r8a66597, td->pipe->fifoaddr, buf, size);
+               if (!usb_pipebulk(urb->pipe) || td->maxpacket != size)
+                       r8a66597_write(r8a66597, BVAL, td->pipe->fifoctr);
+       }
+
+       /* update parameters */
+       urb->actual_length += size;
+       if (usb_pipeisoc(urb->pipe)) {
+               urb->iso_frame_desc[td->iso_cnt].actual_length = size;
+               urb->iso_frame_desc[td->iso_cnt].status = 0;
+               td->iso_cnt++;
+       }
+
+       /* check transfer finish */
+       if (check_transfer_finish(td, urb)) {
+               disable_irq_ready(r8a66597, pipenum);
+               enable_irq_empty(r8a66597, pipenum);
+               if (!usb_pipeisoc(urb->pipe))
+                       enable_irq_nrdy(r8a66597, pipenum);
+       } else
+               pipe_irq_enable(r8a66597, urb, pipenum);
+}
+
+
+static void check_next_phase(struct r8a66597 *r8a66597)
+{
+       struct r8a66597_td *td = r8a66597_get_td(r8a66597, 0);
+       struct urb *urb;
+       u8 finish = 0;
+
+       if (unlikely(!td))
+               return;
+       urb = td->urb;
+
+       switch (td->type) {
+       case USB_PID_IN:
+       case USB_PID_OUT:
+               if (urb->status != -EINPROGRESS) {
+                       finish = 1;
+                       break;
+               }
+               if (check_transfer_finish(td, urb))
+                       td->type = USB_PID_ACK;
+               break;
+       case USB_PID_SETUP:
+               if (urb->status != -EINPROGRESS)
+                       finish = 1;
+               else if (urb->transfer_buffer_length == urb->actual_length) {
+                       td->type = USB_PID_ACK;
+                       urb->status = 0;
+               } else if (usb_pipeout(urb->pipe))
+                       td->type = USB_PID_OUT;
+               else
+                       td->type = USB_PID_IN;
+               break;
+       case USB_PID_ACK:
+               finish = 1;
+               if (urb->status == -EINPROGRESS)
+                       urb->status = 0;
+               break;
+       }
+
+       if (finish)
+               finish_request(r8a66597, td, 0, urb);
+       else
+               start_transfer(r8a66597, td);
+}
+
+static void set_urb_error(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum);
+
+       if (td && td->urb) {
+               u16 pid = r8a66597_read(r8a66597, td->pipe->pipectr) & PID;
+
+               if (pid == PID_NAK)
+                       td->urb->status = -ECONNRESET;
+               else
+                       td->urb->status = -EPIPE;
+       }
+}
+
+static void irq_pipe_ready(struct r8a66597 *r8a66597)
+{
+       u16 check;
+       u16 pipenum;
+       u16 mask;
+       struct r8a66597_td *td;
+
+       mask = r8a66597_read(r8a66597, BRDYSTS)
+              & r8a66597_read(r8a66597, BRDYENB);
+       r8a66597_write(r8a66597, (u16)~mask, BRDYSTS);
+       if (mask & BRDY0) {
+               td = r8a66597_get_td(r8a66597, 0);
+               if (td && td->type == USB_PID_IN)
+                       packet_read(r8a66597, 0);
+               else
+                       pipe_irq_disable(r8a66597, 0);
+               check_next_phase(r8a66597);
+       }
+
+       for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+               check = 1 << pipenum;
+               if (mask & check) {
+                       td = r8a66597_get_td(r8a66597, pipenum);
+                       if (unlikely(!td))
+                               continue;
+
+                       if (td->type == USB_PID_IN)
+                               packet_read(r8a66597, pipenum);
+                       else if (td->type == USB_PID_OUT)
+                               packet_write(r8a66597, pipenum);
+               }
+       }
+}
+
+static void irq_pipe_empty(struct r8a66597 *r8a66597)
+{
+       u16 tmp;
+       u16 check;
+       u16 pipenum;
+       u16 mask;
+       struct r8a66597_td *td;
+
+       mask = r8a66597_read(r8a66597, BEMPSTS)
+              & r8a66597_read(r8a66597, BEMPENB);
+       r8a66597_write(r8a66597, (u16)~mask, BEMPSTS);
+       if (mask & BEMP0) {
+               cfifo_change(r8a66597, 0);
+               td = r8a66597_get_td(r8a66597, 0);
+               if (td && td->type != USB_PID_OUT)
+                       disable_irq_empty(r8a66597, 0);
+               check_next_phase(r8a66597);
+       }
+
+       for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+               check = 1 << pipenum;
+               if (mask &  check) {
+                       struct r8a66597_td *td;
+                       td = r8a66597_get_td(r8a66597, pipenum);
+                       if (unlikely(!td))
+                               continue;
+
+                       tmp = r8a66597_read(r8a66597, td->pipe->pipectr);
+                       if ((tmp & INBUFM) == 0) {
+                               disable_irq_empty(r8a66597, pipenum);
+                               pipe_irq_disable(r8a66597, pipenum);
+                               if (td->urb->status == -EINPROGRESS)
+                                       td->urb->status = 0;
+                               finish_request(r8a66597, td, pipenum, td->urb);
+                       }
+               }
+       }
+}
+
+static void irq_pipe_nrdy(struct r8a66597 *r8a66597)
+{
+       u16 check;
+       u16 pipenum;
+       u16 mask;
+
+       mask = r8a66597_read(r8a66597, NRDYSTS)
+              & r8a66597_read(r8a66597, NRDYENB);
+       r8a66597_write(r8a66597, (u16)~mask, NRDYSTS);
+       if (mask & NRDY0) {
+               cfifo_change(r8a66597, 0);
+               set_urb_error(r8a66597, 0);
+               pipe_irq_disable(r8a66597, 0);
+               check_next_phase(r8a66597);
+       }
+
+       for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+               check = 1 << pipenum;
+               if (mask & check) {
+                       struct r8a66597_td *td;
+                       td = r8a66597_get_td(r8a66597, pipenum);
+                       if (unlikely(!td))
+                               continue;
+
+                       set_urb_error(r8a66597, pipenum);
+                       pipe_irq_disable(r8a66597, pipenum);
+                       pipe_stop(r8a66597, td->pipe);
+                       finish_request(r8a66597, td, pipenum, td->urb);
+               }
+       }
+}
+
+static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port)
+{
+       struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
+       rh->old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
+       rh->scount = R8A66597_MAX_SAMPLING;
+       mod_timer(&r8a66597->rh_timer, jiffies + msecs_to_jiffies(50));
+}
+
+static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
+{
+       struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+       u16 intsts0, intsts1, intsts2;
+       u16 intenb0, intenb1, intenb2;
+       u16 mask0, mask1, mask2;
+
+       spin_lock(&r8a66597->lock);
+
+       intsts0 = r8a66597_read(r8a66597, INTSTS0);
+       intsts1 = r8a66597_read(r8a66597, INTSTS1);
+       intsts2 = r8a66597_read(r8a66597, INTSTS2);
+       intenb0 = r8a66597_read(r8a66597, INTENB0);
+       intenb1 = r8a66597_read(r8a66597, INTENB1);
+       intenb2 = r8a66597_read(r8a66597, INTENB2);
+
+       mask2 = intsts2 & intenb2;
+       mask1 = intsts1 & intenb1;
+       mask0 = intsts0 & intenb0 & (BEMP | NRDY | BRDY);
+       if (mask2) {
+               if (mask2 & ATTCH) {
+                       r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS2);
+                       r8a66597_bclr(r8a66597, ATTCHE, INTENB2);
+
+                       /* start usb bus sampling */
+                       start_root_hub_sampling(r8a66597, 1);
+               }
+               if (mask2 & DTCH) {
+                       r8a66597_write(r8a66597, (u16)~DTCH, INTSTS2);
+                       r8a66597_bclr(r8a66597, DTCHE, INTENB2);
+                       r8a66597_usb_disconnect(r8a66597, 1);
+               }
+       }
+
+       if (mask1) {
+               if (mask1 & ATTCH) {
+                       r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS1);
+                       r8a66597_bclr(r8a66597, ATTCHE, INTENB1);
+
+                       /* start usb bus sampling */
+                       start_root_hub_sampling(r8a66597, 0);
+               }
+               if (mask1 & DTCH) {
+                       r8a66597_write(r8a66597, (u16)~DTCH, INTSTS1);
+                       r8a66597_bclr(r8a66597, DTCHE, INTENB1);
+                       r8a66597_usb_disconnect(r8a66597, 0);
+               }
+               if (mask1 & SIGN) {
+                       r8a66597_write(r8a66597, (u16)~SIGN, INTSTS1);
+                       set_urb_error(r8a66597, 0);
+                       check_next_phase(r8a66597);
+               }
+               if (mask1 & SACK) {
+                       r8a66597_write(r8a66597, (u16)~SACK, INTSTS1);
+                       check_next_phase(r8a66597);
+               }
+       }
+       if (mask0) {
+               if (mask0 & BRDY)
+                       irq_pipe_ready(r8a66597);
+               if (mask0 & BEMP)
+                       irq_pipe_empty(r8a66597);
+               if (mask0 & NRDY)
+                       irq_pipe_nrdy(r8a66597);
+       }
+
+       spin_unlock(&r8a66597->lock);
+       return IRQ_HANDLED;
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port)
+{
+       u16 tmp;
+       struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
+       if (rh->port & (1 << USB_PORT_FEAT_RESET)) {
+               unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+               tmp = r8a66597_read(r8a66597, dvstctr_reg);
+               if ((tmp & USBRST) == USBRST) {
+                       r8a66597_mdfy(r8a66597, UACT, USBRST | UACT,
+                                     dvstctr_reg);
+                       mod_timer(&r8a66597->rh_timer,
+                                 jiffies + msecs_to_jiffies(50));
+               } else
+                       r8a66597_usb_connect(r8a66597, port);
+       }
+
+       if (rh->scount > 0) {
+               tmp = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
+               if (tmp == rh->old_syssts) {
+                       rh->scount--;
+                       if (rh->scount == 0) {
+                               if (tmp == FS_JSTS) {
+                                       r8a66597_bset(r8a66597, HSE,
+                                                     get_syscfg_reg(port));
+                                       r8a66597_usb_preconnect(r8a66597, port);
+                               } else if (tmp == LS_JSTS) {
+                                       r8a66597_bclr(r8a66597, HSE,
+                                                     get_syscfg_reg(port));
+                                       r8a66597_usb_preconnect(r8a66597, port);
+                               } else if (tmp == SE0)
+                                       r8a66597_bset(r8a66597, ATTCHE,
+                                                     get_intenb_reg(port));
+                       } else {
+                               mod_timer(&r8a66597->rh_timer,
+                                         jiffies + msecs_to_jiffies(50));
+                       }
+               } else {
+                       rh->scount = R8A66597_MAX_SAMPLING;
+                       rh->old_syssts = tmp;
+                       mod_timer(&r8a66597->rh_timer,
+                                 jiffies + msecs_to_jiffies(50));
+               }
+       }
+}
+
+static void r8a66597_td_timer(unsigned long _r8a66597)
+{
+       struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
+       unsigned long flags;
+       u16 pipenum;
+       struct r8a66597_td *td, *new_td = NULL;
+       struct r8a66597_pipe *pipe;
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+       for (pipenum = 0; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+               if (!(r8a66597->timeout_map & (1 << pipenum)))
+                       continue;
+               if (timer_pending(&r8a66597->td_timer[pipenum]))
+                       continue;
+
+               td = r8a66597_get_td(r8a66597, pipenum);
+               if (!td) {
+                       r8a66597->timeout_map &= ~(1 << pipenum);
+                       continue;
+               }
+
+               if (td->urb->actual_length) {
+                       set_td_timer(r8a66597, td);
+                       break;
+               }
+
+               pipe = td->pipe;
+               pipe_stop(r8a66597, pipe);
+
+               new_td = td;
+               do {
+                       list_move_tail(&new_td->queue,
+                                      &r8a66597->pipe_queue[pipenum]);
+                       new_td = r8a66597_get_td(r8a66597, pipenum);
+                       if (!new_td) {
+                               new_td = td;
+                               break;
+                       }
+               } while (td != new_td && td->address == new_td->address);
+
+               start_transfer(r8a66597, new_td);
+
+               if (td == new_td)
+                       r8a66597->timeout_map &= ~(1 << pipenum);
+               else
+                       set_td_timer(r8a66597, new_td);
+               break;
+       }
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
+static void r8a66597_timer(unsigned long _r8a66597)
+{
+       struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
+       unsigned long flags;
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+
+       r8a66597_root_hub_control(r8a66597, 0);
+       r8a66597_root_hub_control(r8a66597, 1);
+
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
+static int check_pipe_config(struct r8a66597 *r8a66597, struct urb *urb)
+{
+       struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+
+       if (dev && dev->address && dev->state != USB_STATE_CONFIGURED &&
+           (urb->dev->state == USB_STATE_CONFIGURED))
+               return 1;
+       else
+               return 0;
+}
+
+static int r8a66597_start(struct usb_hcd *hcd)
+{
+       struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+       int ret;
+
+       hcd->state = HC_STATE_RUNNING;
+       if ((ret = enable_controller(r8a66597)) < 0)
+               return ret;
+
+       return 0;
+}
+
+static void r8a66597_stop(struct usb_hcd *hcd)
+{
+       struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+
+       disable_controller(r8a66597);
+}
+
+static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb)
+{
+       unsigned int usb_address = usb_pipedevice(urb->pipe);
+       u16 root_port, hub_port;
+
+       if (usb_address == 0) {
+               get_port_number(urb->dev->devpath,
+                               &root_port, &hub_port);
+               set_devadd_reg(r8a66597, 0,
+                              get_r8a66597_usb_speed(urb->dev->speed),
+                              get_parent_r8a66597_address(r8a66597, urb->dev),
+                              hub_port, root_port);
+       }
+}
+
+static struct r8a66597_td *r8a66597_make_td(struct r8a66597 *r8a66597,
+                                           struct urb *urb,
+                                           struct usb_host_endpoint *hep,
+                                           gfp_t mem_flags)
+{
+       struct r8a66597_td *td;
+       u16 pipenum;
+
+       td = kzalloc(sizeof(struct r8a66597_td), mem_flags);
+       if (td == NULL)
+               return NULL;
+
+       pipenum = r8a66597_get_pipenum(urb, hep);
+       td->pipenum = pipenum;
+       td->pipe = hep->hcpriv;
+       td->urb = urb;
+       td->address = get_urb_to_r8a66597_addr(r8a66597, urb);
+       td->maxpacket = usb_maxpacket(urb->dev, urb->pipe,
+                                     !usb_pipein(urb->pipe));
+       if (usb_pipecontrol(urb->pipe))
+               td->type = USB_PID_SETUP;
+       else if (usb_pipein(urb->pipe))
+               td->type = USB_PID_IN;
+       else
+               td->type = USB_PID_OUT;
+       INIT_LIST_HEAD(&td->queue);
+
+       return td;
+}
+
+static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
+                               struct usb_host_endpoint *hep,
+                               struct urb *urb,
+                               gfp_t mem_flags)
+{
+       struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+       struct r8a66597_td *td = NULL;
+       int ret = 0, request = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+       if (!get_urb_to_r8a66597_dev(r8a66597, urb)) {
+               ret = -ENODEV;
+               goto error;
+       }
+
+       if (!hep->hcpriv) {
+               hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), mem_flags);
+               if (!hep->hcpriv) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
+               set_pipe_reg_addr(hep->hcpriv, R8A66597_PIPE_NO_DMA);
+               if (usb_pipeendpoint(urb->pipe))
+                       init_pipe_info(r8a66597, urb, hep, &hep->desc);
+       }
+
+       if (unlikely(check_pipe_config(r8a66597, urb)))
+               init_pipe_config(r8a66597, urb);
+
+       set_address_zero(r8a66597, urb);
+       td = r8a66597_make_td(r8a66597, urb, hep, mem_flags);
+       if (td == NULL) {
+               ret = -ENOMEM;
+               goto error;
+       }
+       if (list_empty(&r8a66597->pipe_queue[td->pipenum]))
+               request = 1;
+       list_add_tail(&td->queue, &r8a66597->pipe_queue[td->pipenum]);
+
+       spin_lock(&urb->lock);
+       if (urb->status != -EINPROGRESS) {
+               spin_unlock(&urb->lock);
+               ret = -EPIPE;
+               goto error;
+       }
+       urb->hcpriv = td;
+       spin_unlock(&urb->lock);
+
+       if (request) {
+               ret = start_transfer(r8a66597, td);
+               if (ret < 0) {
+                       list_del(&td->queue);
+                       kfree(td);
+               }
+       } else
+               set_td_timer(r8a66597, td);
+
+error:
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+       return ret;
+}
+
+static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+{
+       struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+       struct r8a66597_td *td;
+       unsigned long flags;
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+       if (urb->hcpriv) {
+               td = urb->hcpriv;
+               pipe_stop(r8a66597, td->pipe);
+               pipe_irq_disable(r8a66597, td->pipenum);
+               disable_irq_empty(r8a66597, td->pipenum);
+               done(r8a66597, td, td->pipenum, urb);
+       }
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+       return 0;
+}
+
+static void r8a66597_endpoint_disable(struct usb_hcd *hcd,
+                                     struct usb_host_endpoint *hep)
+{
+       struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+       struct r8a66597_pipe *pipe = (struct r8a66597_pipe *)hep->hcpriv;
+       struct r8a66597_td *td;
+       struct urb *urb = NULL;
+       u16 pipenum;
+       unsigned long flags;
+
+       if (pipe == NULL)
+               return;
+       pipenum = pipe->info.pipenum;
+
+       if (pipenum == 0) {
+               kfree(hep->hcpriv);
+               hep->hcpriv = NULL;
+               return;
+       }
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+       pipe_stop(r8a66597, pipe);
+       pipe_irq_disable(r8a66597, pipenum);
+       disable_irq_empty(r8a66597, pipenum);
+       td = r8a66597_get_td(r8a66597, pipenum);
+       if (td)
+               urb = td->urb;
+       done(r8a66597, td, pipenum, urb);
+       kfree(hep->hcpriv);
+       hep->hcpriv = NULL;
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
+static int r8a66597_get_frame(struct usb_hcd *hcd)
+{
+       struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+       return r8a66597_read(r8a66597, FRMNUM) & 0x03FF;
+}
+
+static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)
+{
+       int chix;
+
+       if (udev->state == USB_STATE_CONFIGURED &&
+           udev->parent && udev->parent->devnum > 1 &&
+           udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)
+               map[udev->devnum/32] |= (1 << (udev->devnum % 32));
+
+       for (chix = 0; chix < udev->maxchild; chix++) {
+               struct usb_device *childdev = udev->children[chix];
+
+               if (childdev)
+                       collect_usb_address_map(childdev, map);
+       }
+}
+
+/* this function must be called with interrupt disabled */
+static struct r8a66597_device *get_r8a66597_device(struct r8a66597 *r8a66597,
+                                                  int addr)
+{
+       struct r8a66597_device *dev;
+       struct list_head *list = &r8a66597->child_device;
+
+       list_for_each_entry(dev, list, device_list) {
+               if (!dev)
+                       continue;
+               if (dev->usb_address != addr)
+                       continue;
+
+               return dev;
+       }
+
+       err("get_r8a66597_device fail.(%d)\n", addr);
+       return NULL;
+}
+
+static void update_usb_address_map(struct r8a66597 *r8a66597,
+                                  struct usb_device *root_hub,
+                                  unsigned long *map)
+{
+       int i, j, addr;
+       unsigned long diff;
+       unsigned long flags;
+
+       for (i = 0; i < 4; i++) {
+               diff = r8a66597->child_connect_map[i] ^ map[i];
+               if (!diff)
+                       continue;
+
+               for (j = 0; j < 32; j++) {
+                       if (!(diff & (1 << j)))
+                               continue;
+
+                       addr = i * 32 + j;
+                       if (map[i] & (1 << j))
+                               set_child_connect_map(r8a66597, addr);
+                       else {
+                               struct r8a66597_device *dev;
+
+                               spin_lock_irqsave(&r8a66597->lock, flags);
+                               dev = get_r8a66597_device(r8a66597, addr);
+                               disable_r8a66597_pipe_all(r8a66597, dev);
+                               free_usb_address(r8a66597, dev);
+                               put_child_connect_map(r8a66597, addr);
+                               spin_unlock_irqrestore(&r8a66597->lock, flags);
+                       }
+               }
+       }
+}
+
+static void r8a66597_check_detect_child(struct r8a66597 *r8a66597,
+                                       struct usb_hcd *hcd)
+{
+       struct usb_bus *bus;
+       unsigned long now_map[4];
+
+       memset(now_map, 0, sizeof(now_map));
+
+       list_for_each_entry(bus, &usb_bus_list, bus_list) {
+               if (!bus->root_hub)
+                       continue;
+
+               if (bus->busnum != hcd->self.busnum)
+                       continue;
+
+               collect_usb_address_map(bus->root_hub, now_map);
+               update_usb_address_map(r8a66597, bus->root_hub, now_map);
+       }
+}
+
+static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+       struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+       unsigned long flags;
+       int i;
+
+       r8a66597_check_detect_child(r8a66597, hcd);
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+
+       *buf = 0;       /* initialize (no change) */
+
+       for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++) {
+               if (r8a66597->root_hub[i].port & 0xffff0000)
+                       *buf |= 1 << (i + 1);
+       }
+
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+
+       return (*buf != 0);
+}
+
+static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597,
+                                   struct usb_hub_descriptor *desc)
+{
+       desc->bDescriptorType = 0x29;
+       desc->bHubContrCurrent = 0;
+       desc->bNbrPorts = R8A66597_MAX_ROOT_HUB;
+       desc->bDescLength = 9;
+       desc->bPwrOn2PwrGood = 0;
+       desc->wHubCharacteristics = cpu_to_le16(0x0011);
+       desc->bitmap[0] = ((1 << R8A66597_MAX_ROOT_HUB) - 1) << 1;
+       desc->bitmap[1] = ~0;
+}
+
+static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+                               u16 wIndex, char *buf, u16 wLength)
+{
+       struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+       int ret;
+       int port = (wIndex & 0x00FF) - 1;
+       struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+       unsigned long flags;
+
+       ret = 0;
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+       switch (typeReq) {
+       case ClearHubFeature:
+       case SetHubFeature:
+               switch (wValue) {
+               case C_HUB_OVER_CURRENT:
+               case C_HUB_LOCAL_POWER:
+                       break;
+               default:
+                       goto error;
+               }
+               break;
+       case ClearPortFeature:
+               if (wIndex > R8A66597_MAX_ROOT_HUB)
+                       goto error;
+               if (wLength != 0)
+                       goto error;
+
+               switch (wValue) {
+               case USB_PORT_FEAT_ENABLE:
+                       rh->port &= (1 << USB_PORT_FEAT_POWER);
+                       break;
+               case USB_PORT_FEAT_SUSPEND:
+                       break;
+               case USB_PORT_FEAT_POWER:
+                       r8a66597_port_power(r8a66597, port, 0);
+                       break;
+               case USB_PORT_FEAT_C_ENABLE:
+               case USB_PORT_FEAT_C_SUSPEND:
+               case USB_PORT_FEAT_C_CONNECTION:
+               case USB_PORT_FEAT_C_OVER_CURRENT:
+               case USB_PORT_FEAT_C_RESET:
+                       break;
+               default:
+                       goto error;
+               }
+               rh->port &= ~(1 << wValue);
+               break;
+       case GetHubDescriptor:
+               r8a66597_hub_descriptor(r8a66597,
+                                       (struct usb_hub_descriptor *)buf);
+               break;
+       case GetHubStatus:
+               *buf = 0x00;
+               break;
+       case GetPortStatus:
+               if (wIndex > R8A66597_MAX_ROOT_HUB)
+                       goto error;
+               *(u32 *)buf = rh->port;
+               break;
+       case SetPortFeature:
+               if (wIndex > R8A66597_MAX_ROOT_HUB)
+                       goto error;
+               if (wLength != 0)
+                       goto error;
+
+               switch (wValue) {
+               case USB_PORT_FEAT_SUSPEND:
+                       break;
+               case USB_PORT_FEAT_POWER:
+                       r8a66597_port_power(r8a66597, port, 1);
+                       rh->port |= (1 << USB_PORT_FEAT_POWER);
+                       break;
+               case USB_PORT_FEAT_RESET: {
+                       struct r8a66597_device *dev = rh->dev;
+
+                       rh->port |= (1 << USB_PORT_FEAT_RESET);
+
+                       disable_r8a66597_pipe_all(r8a66597, dev);
+                       free_usb_address(r8a66597, dev);
+
+                       r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT,
+                                     get_dvstctr_reg(port));
+                       mod_timer(&r8a66597->rh_timer,
+                                 jiffies + msecs_to_jiffies(50));
+                       }
+                       break;
+               default:
+                       goto error;
+               }
+               rh->port |= 1 << wValue;
+               break;
+       default:
+error:
+               ret = -EPIPE;
+               break;
+       }
+
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+       return ret;
+}
+
+static struct hc_driver r8a66597_hc_driver = {
+       .description =          hcd_name,
+       .hcd_priv_size =        sizeof(struct r8a66597),
+       .irq =                  r8a66597_irq,
+
+       /*
+        * generic hardware linkage
+        */
+       .flags =                HCD_USB2,
+
+       .start =                r8a66597_start,
+       .stop =                 r8a66597_stop,
+
+       /*
+        * managing i/o requests and associated device resources
+        */
+       .urb_enqueue =          r8a66597_urb_enqueue,
+       .urb_dequeue =          r8a66597_urb_dequeue,
+       .endpoint_disable =     r8a66597_endpoint_disable,
+
+       /*
+        * periodic schedule support
+        */
+       .get_frame_number =     r8a66597_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_status_data =      r8a66597_hub_status_data,
+       .hub_control =          r8a66597_hub_control,
+};
+
+#if defined(CONFIG_PM)
+static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       pdev->dev.power.power_state = state;
+       return 0;
+}
+
+static int r8a66597_resume(struct platform_device *pdev)
+{
+       pdev->dev.power.power_state = PMSG_ON;
+       return 0;
+}
+#else  /* if defined(CONFIG_PM) */
+#define r8a66597_suspend       NULL
+#define r8a66597_resume                NULL
+#endif
+
+static int __init_or_module r8a66597_remove(struct platform_device *pdev)
+{
+       struct r8a66597         *r8a66597 = dev_get_drvdata(&pdev->dev);
+       struct usb_hcd          *hcd = r8a66597_to_hcd(r8a66597);
+
+       del_timer_sync(&r8a66597->rh_timer);
+       iounmap((void *)r8a66597->reg);
+       usb_remove_hcd(hcd);
+       usb_put_hcd(hcd);
+       return 0;
+}
+
+#define resource_len(r) (((r)->end - (r)->start) + 1)
+static int __init r8a66597_probe(struct platform_device *pdev)
+{
+       struct resource *res = NULL;
+       int irq = -1;
+       void __iomem *reg = NULL;
+       struct usb_hcd *hcd = NULL;
+       struct r8a66597 *r8a66597;
+       int ret = 0;
+       int i;
+
+       if (pdev->dev.dma_mask) {
+               ret = -EINVAL;
+               err("dma not support");
+               goto clean_up;
+       }
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                          (char *)hcd_name);
+       if (!res) {
+               ret = -ENODEV;
+               err("platform_get_resource_byname error.");
+               goto clean_up;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               ret = -ENODEV;
+               err("platform_get_irq error.");
+               goto clean_up;
+       }
+
+       reg = ioremap(res->start, resource_len(res));
+       if (reg == NULL) {
+               ret = -ENOMEM;
+               err("ioremap error.");
+               goto clean_up;
+       }
+
+       /* initialize hcd */
+       hcd = usb_create_hcd(&r8a66597_hc_driver, &pdev->dev, (char *)hcd_name);
+       if (!hcd) {
+               ret = -ENOMEM;
+               err("Failed to create hcd");
+               goto clean_up;
+       }
+       r8a66597 = hcd_to_r8a66597(hcd);
+       memset(r8a66597, 0, sizeof(struct r8a66597));
+       dev_set_drvdata(&pdev->dev, r8a66597);
+
+       spin_lock_init(&r8a66597->lock);
+       init_timer(&r8a66597->rh_timer);
+       r8a66597->rh_timer.function = r8a66597_timer;
+       r8a66597->rh_timer.data = (unsigned long)r8a66597;
+       r8a66597->reg = (unsigned long)reg;
+
+       for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) {
+               INIT_LIST_HEAD(&r8a66597->pipe_queue[i]);
+               init_timer(&r8a66597->td_timer[i]);
+               r8a66597->td_timer[i].function = r8a66597_td_timer;
+               r8a66597->td_timer[i].data = (unsigned long)r8a66597;
+       }
+       INIT_LIST_HEAD(&r8a66597->child_device);
+
+       hcd->rsrc_start = res->start;
+       ret = usb_add_hcd(hcd, irq, 0);
+       if (ret != 0) {
+               err("Failed to add hcd");
+               goto clean_up;
+       }
+
+       return 0;
+
+clean_up:
+       if (reg)
+               iounmap(reg);
+       if (res)
+               release_mem_region(res->start, 1);
+
+       return ret;
+}
+
+static struct platform_driver r8a66597_driver = {
+       .probe =        r8a66597_probe,
+       .remove =       r8a66597_remove,
+       .suspend =      r8a66597_suspend,
+       .resume =       r8a66597_resume,
+       .driver         = {
+               .name = (char *) hcd_name,
+       },
+};
+
+static int __init r8a66597_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       info("driver %s, %s", hcd_name, DRIVER_VERSION);
+       return platform_driver_register(&r8a66597_driver);
+}
+module_init(r8a66597_init);
+
+static void __exit r8a66597_cleanup(void)
+{
+       platform_driver_unregister(&r8a66597_driver);
+}
+module_exit(r8a66597_cleanup);
+
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
new file mode 100644 (file)
index 0000000..97c2a71
--- /dev/null
@@ -0,0 +1,634 @@
+/*
+ * R8A66597 HCD (Host Controller Driver)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ * Portions Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
+ * Portions Copyright (C) 2004-2005 David Brownell
+ * Portions Copyright (C) 1999 Roman Weissgaerber
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __R8A66597_H__
+#define __R8A66597_H__
+
+#define SYSCFG0                0x00
+#define SYSCFG1                0x02
+#define SYSSTS0                0x04
+#define SYSSTS1                0x06
+#define DVSTCTR0       0x08
+#define DVSTCTR1       0x0A
+#define TESTMODE       0x0C
+#define PINCFG         0x0E
+#define DMA0CFG                0x10
+#define DMA1CFG                0x12
+#define CFIFO          0x14
+#define D0FIFO         0x18
+#define D1FIFO         0x1C
+#define CFIFOSEL       0x20
+#define CFIFOCTR       0x22
+#define CFIFOSIE       0x24
+#define D0FIFOSEL      0x28
+#define D0FIFOCTR      0x2A
+#define D1FIFOSEL      0x2C
+#define D1FIFOCTR      0x2E
+#define INTENB0                0x30
+#define INTENB1                0x32
+#define INTENB2                0x34
+#define BRDYENB                0x36
+#define NRDYENB                0x38
+#define BEMPENB                0x3A
+#define SOFCFG         0x3C
+#define INTSTS0                0x40
+#define INTSTS1                0x42
+#define INTSTS2                0x44
+#define BRDYSTS                0x46
+#define NRDYSTS                0x48
+#define BEMPSTS                0x4A
+#define FRMNUM         0x4C
+#define UFRMNUM                0x4E
+#define USBADDR                0x50
+#define USBREQ         0x54
+#define USBVAL         0x56
+#define USBINDX                0x58
+#define USBLENG                0x5A
+#define DCPCFG         0x5C
+#define DCPMAXP                0x5E
+#define DCPCTR         0x60
+#define PIPESEL                0x64
+#define PIPECFG                0x68
+#define PIPEBUF                0x6A
+#define PIPEMAXP       0x6C
+#define PIPEPERI       0x6E
+#define PIPE1CTR       0x70
+#define PIPE2CTR       0x72
+#define PIPE3CTR       0x74
+#define PIPE4CTR       0x76
+#define PIPE5CTR       0x78
+#define PIPE6CTR       0x7A
+#define PIPE7CTR       0x7C
+#define PIPE8CTR       0x7E
+#define PIPE9CTR       0x80
+#define PIPE1TRE       0x90
+#define PIPE1TRN       0x92
+#define PIPE2TRE       0x94
+#define PIPE2TRN       0x96
+#define PIPE3TRE       0x98
+#define PIPE3TRN       0x9A
+#define PIPE4TRE       0x9C
+#define        PIPE4TRN        0x9E
+#define        PIPE5TRE        0xA0
+#define        PIPE5TRN        0xA2
+#define DEVADD0                0xD0
+#define DEVADD1                0xD2
+#define DEVADD2                0xD4
+#define DEVADD3                0xD6
+#define DEVADD4                0xD8
+#define DEVADD5                0xDA
+#define DEVADD6                0xDC
+#define DEVADD7                0xDE
+#define DEVADD8                0xE0
+#define DEVADD9                0xE2
+#define DEVADDA                0xE4
+
+/* System Configuration Control Register */
+#define        XTAL            0xC000  /* b15-14: Crystal selection */
+#define          XTAL48         0x8000   /* 48MHz */
+#define          XTAL24         0x4000   /* 24MHz */
+#define          XTAL12         0x0000   /* 12MHz */
+#define        XCKE            0x2000  /* b13: External clock enable */
+#define        PLLC            0x0800  /* b11: PLL control */
+#define        SCKE            0x0400  /* b10: USB clock enable */
+#define        PCSDIS          0x0200  /* b9: not CS wakeup */
+#define        LPSME           0x0100  /* b8: Low power sleep mode */
+#define        HSE             0x0080  /* b7: Hi-speed enable */
+#define        DCFM            0x0040  /* b6: Controller function select  */
+#define        DRPD            0x0020  /* b5: D+/- pull down control */
+#define        DPRPU           0x0010  /* b4: D+ pull up control */
+#define        USBE            0x0001  /* b0: USB module operation enable */
+
+/* System Configuration Status Register */
+#define        OVCBIT          0x8000  /* b15-14: Over-current bit */
+#define        OVCMON          0xC000  /* b15-14: Over-current monitor */
+#define        SOFEA           0x0020  /* b5: SOF monitor */
+#define        IDMON           0x0004  /* b3: ID-pin monitor */
+#define        LNST            0x0003  /* b1-0: D+, D- line status */
+#define          SE1            0x0003   /* SE1 */
+#define          FS_KSTS        0x0002   /* Full-Speed K State */
+#define          FS_JSTS        0x0001   /* Full-Speed J State */
+#define          LS_JSTS        0x0002   /* Low-Speed J State */
+#define          LS_KSTS        0x0001   /* Low-Speed K State */
+#define          SE0            0x0000   /* SE0 */
+
+/* Device State Control Register */
+#define        EXTLP0          0x0400  /* b10: External port */
+#define        VBOUT           0x0200  /* b9: VBUS output */
+#define        WKUP            0x0100  /* b8: Remote wakeup */
+#define        RWUPE           0x0080  /* b7: Remote wakeup sense */
+#define        USBRST          0x0040  /* b6: USB reset enable */
+#define        RESUME          0x0020  /* b5: Resume enable */
+#define        UACT            0x0010  /* b4: USB bus enable */
+#define        RHST            0x0007  /* b1-0: Reset handshake status */
+#define          HSPROC         0x0004   /* HS handshake is processing */
+#define          HSMODE         0x0003   /* Hi-Speed mode */
+#define          FSMODE         0x0002   /* Full-Speed mode */
+#define          LSMODE         0x0001   /* Low-Speed mode */
+#define          UNDECID        0x0000   /* Undecided */
+
+/* Test Mode Register */
+#define        UTST                    0x000F  /* b3-0: Test select */
+#define          H_TST_PACKET           0x000C   /* HOST TEST Packet */
+#define          H_TST_SE0_NAK          0x000B   /* HOST TEST SE0 NAK */
+#define          H_TST_K                0x000A   /* HOST TEST K */
+#define          H_TST_J                0x0009   /* HOST TEST J */
+#define          H_TST_NORMAL           0x0000   /* HOST Normal Mode */
+#define          P_TST_PACKET           0x0004   /* PERI TEST Packet */
+#define          P_TST_SE0_NAK          0x0003   /* PERI TEST SE0 NAK */
+#define          P_TST_K                0x0002   /* PERI TEST K */
+#define          P_TST_J                0x0001   /* PERI TEST J */
+#define          P_TST_NORMAL           0x0000   /* PERI Normal Mode */
+
+/* Data Pin Configuration Register */
+#define        LDRV                    0x8000  /* b15: Drive Current Adjust */
+#define          VIF1                    0x0000                /* VIF = 1.8V */
+#define          VIF3                    0x8000                /* VIF = 3.3V */
+#define        INTA                    0x0001  /* b1: USB INT-pin active */
+
+/* DMAx Pin Configuration Register */
+#define        DREQA                   0x4000  /* b14: Dreq active select */
+#define        BURST                   0x2000  /* b13: Burst mode */
+#define        DACKA                   0x0400  /* b10: Dack active select */
+#define        DFORM                   0x0380  /* b9-7: DMA mode select */
+#define          CPU_ADR_RD_WR          0x0000   /* Address + RD/WR mode (CPU bus) */
+#define          CPU_DACK_RD_WR         0x0100   /* DACK + RD/WR mode (CPU bus) */
+#define          CPU_DACK_ONLY          0x0180   /* DACK only mode (CPU bus) */
+#define          SPLIT_DACK_ONLY        0x0200   /* DACK only mode (SPLIT bus) */
+#define        DENDA                   0x0040  /* b6: Dend active select */
+#define        PKTM                    0x0020  /* b5: Packet mode */
+#define        DENDE                   0x0010  /* b4: Dend enable */
+#define        OBUS                    0x0004  /* b2: OUTbus mode */
+
+/* CFIFO/DxFIFO Port Select Register */
+#define        RCNT            0x8000  /* b15: Read count mode */
+#define        REW             0x4000  /* b14: Buffer rewind */
+#define        DCLRM           0x2000  /* b13: DMA buffer clear mode */
+#define        DREQE           0x1000  /* b12: DREQ output enable */
+#define        MBW             0x0400  /* b10: Maximum bit width for FIFO access */
+#define          MBW_8          0x0000   /*  8bit */
+#define          MBW_16         0x0400   /* 16bit */
+#define        BIGEND          0x0100  /* b8: Big endian mode */
+#define          BYTE_LITTLE    0x0000         /* little dendian */
+#define          BYTE_BIG       0x0100         /* big endifan */
+#define        ISEL            0x0020  /* b5: DCP FIFO port direction select */
+#define        CURPIPE         0x000F  /* b2-0: PIPE select */
+
+/* CFIFO/DxFIFO Port Control Register */
+#define        BVAL            0x8000  /* b15: Buffer valid flag */
+#define        BCLR            0x4000  /* b14: Buffer clear */
+#define        FRDY            0x2000  /* b13: FIFO ready */
+#define        DTLN            0x0FFF  /* b11-0: FIFO received data length */
+
+/* Interrupt Enable Register 0 */
+#define        VBSE            0x8000  /* b15: VBUS interrupt */
+#define        RSME            0x4000  /* b14: Resume interrupt */
+#define        SOFE            0x2000  /* b13: Frame update interrupt */
+#define        DVSE            0x1000  /* b12: Device state transition interrupt */
+#define        CTRE            0x0800  /* b11: Control transfer stage transition interrupt */
+#define        BEMPE           0x0400  /* b10: Buffer empty interrupt */
+#define        NRDYE           0x0200  /* b9: Buffer not ready interrupt */
+#define        BRDYE           0x0100  /* b8: Buffer ready interrupt */
+
+/* Interrupt Enable Register 1 */
+#define        OVRCRE          0x8000  /* b15: Over-current interrupt */
+#define        BCHGE           0x4000  /* b14: USB us chenge interrupt */
+#define        DTCHE           0x1000  /* b12: Detach sense interrupt */
+#define        ATTCHE          0x0800  /* b11: Attach sense interrupt */
+#define        EOFERRE         0x0040  /* b6: EOF error interrupt */
+#define        SIGNE           0x0020  /* b5: SETUP IGNORE interrupt */
+#define        SACKE           0x0010  /* b4: SETUP ACK interrupt */
+
+/* BRDY Interrupt Enable/Status Register */
+#define        BRDY9           0x0200  /* b9: PIPE9 */
+#define        BRDY8           0x0100  /* b8: PIPE8 */
+#define        BRDY7           0x0080  /* b7: PIPE7 */
+#define        BRDY6           0x0040  /* b6: PIPE6 */
+#define        BRDY5           0x0020  /* b5: PIPE5 */
+#define        BRDY4           0x0010  /* b4: PIPE4 */
+#define        BRDY3           0x0008  /* b3: PIPE3 */
+#define        BRDY2           0x0004  /* b2: PIPE2 */
+#define        BRDY1           0x0002  /* b1: PIPE1 */
+#define        BRDY0           0x0001  /* b1: PIPE0 */
+
+/* NRDY Interrupt Enable/Status Register */
+#define        NRDY9           0x0200  /* b9: PIPE9 */
+#define        NRDY8           0x0100  /* b8: PIPE8 */
+#define        NRDY7           0x0080  /* b7: PIPE7 */
+#define        NRDY6           0x0040  /* b6: PIPE6 */
+#define        NRDY5           0x0020  /* b5: PIPE5 */
+#define        NRDY4           0x0010  /* b4: PIPE4 */
+#define        NRDY3           0x0008  /* b3: PIPE3 */
+#define        NRDY2           0x0004  /* b2: PIPE2 */
+#define        NRDY1           0x0002  /* b1: PIPE1 */
+#define        NRDY0           0x0001  /* b1: PIPE0 */
+
+/* BEMP Interrupt Enable/Status Register */
+#define        BEMP9           0x0200  /* b9: PIPE9 */
+#define        BEMP8           0x0100  /* b8: PIPE8 */
+#define        BEMP7           0x0080  /* b7: PIPE7 */
+#define        BEMP6           0x0040  /* b6: PIPE6 */
+#define        BEMP5           0x0020  /* b5: PIPE5 */
+#define        BEMP4           0x0010  /* b4: PIPE4 */
+#define        BEMP3           0x0008  /* b3: PIPE3 */
+#define        BEMP2           0x0004  /* b2: PIPE2 */
+#define        BEMP1           0x0002  /* b1: PIPE1 */
+#define        BEMP0           0x0001  /* b0: PIPE0 */
+
+/* SOF Pin Configuration Register */
+#define        TRNENSEL        0x0100  /* b8: Select transaction enable period */
+#define        BRDYM           0x0040  /* b6: BRDY clear timing */
+#define        INTL            0x0020  /* b5: Interrupt sense select */
+#define        EDGESTS         0x0010  /* b4:  */
+#define        SOFMODE         0x000C  /* b3-2: SOF pin select */
+#define          SOF_125US      0x0008   /* SOF OUT 125us Frame Signal */
+#define          SOF_1MS        0x0004   /* SOF OUT 1ms Frame Signal */
+#define          SOF_DISABLE    0x0000   /* SOF OUT Disable */
+
+/* Interrupt Status Register 0 */
+#define        VBINT           0x8000  /* b15: VBUS interrupt */
+#define        RESM            0x4000  /* b14: Resume interrupt */
+#define        SOFR            0x2000  /* b13: SOF frame update interrupt */
+#define        DVST            0x1000  /* b12: Device state transition interrupt */
+#define        CTRT            0x0800  /* b11: Control transfer stage transition interrupt */
+#define        BEMP            0x0400  /* b10: Buffer empty interrupt */
+#define        NRDY            0x0200  /* b9: Buffer not ready interrupt */
+#define        BRDY            0x0100  /* b8: Buffer ready interrupt */
+#define        VBSTS           0x0080  /* b7: VBUS input port */
+#define        DVSQ            0x0070  /* b6-4: Device state */
+#define          DS_SPD_CNFG    0x0070   /* Suspend Configured */
+#define          DS_SPD_ADDR    0x0060   /* Suspend Address */
+#define          DS_SPD_DFLT    0x0050   /* Suspend Default */
+#define          DS_SPD_POWR    0x0040   /* Suspend Powered */
+#define          DS_SUSP        0x0040   /* Suspend */
+#define          DS_CNFG        0x0030   /* Configured */
+#define          DS_ADDS        0x0020   /* Address */
+#define          DS_DFLT        0x0010   /* Default */
+#define          DS_POWR        0x0000   /* Powered */
+#define        DVSQS           0x0030  /* b5-4: Device state */
+#define        VALID           0x0008  /* b3: Setup packet detected flag */
+#define        CTSQ            0x0007  /* b2-0: Control transfer stage */
+#define          CS_SQER        0x0006   /* Sequence error */
+#define          CS_WRND        0x0005   /* Control write nodata status stage */
+#define          CS_WRSS        0x0004   /* Control write status stage */
+#define          CS_WRDS        0x0003   /* Control write data stage */
+#define          CS_RDSS        0x0002   /* Control read status stage */
+#define          CS_RDDS        0x0001   /* Control read data stage */
+#define          CS_IDST        0x0000   /* Idle or setup stage */
+
+/* Interrupt Status Register 1 */
+#define        OVRCR           0x8000  /* b15: Over-current interrupt */
+#define        BCHG            0x4000  /* b14: USB bus chenge interrupt */
+#define        DTCH            0x1000  /* b12: Detach sense interrupt */
+#define        ATTCH           0x0800  /* b11: Attach sense interrupt */
+#define        EOFERR          0x0040  /* b6: EOF-error interrupt */
+#define        SIGN            0x0020  /* b5: Setup ignore interrupt */
+#define        SACK            0x0010  /* b4: Setup acknowledge interrupt */
+
+/* Frame Number Register */
+#define        OVRN            0x8000  /* b15: Overrun error */
+#define        CRCE            0x4000  /* b14: Received data error */
+#define        FRNM            0x07FF  /* b10-0: Frame number */
+
+/* Micro Frame Number Register */
+#define        UFRNM           0x0007  /* b2-0: Micro frame number */
+
+/* USB Address / Low Power Status Recovery Register */
+//#define      USBADDR         0x007F  /* b6-0: USB address */
+
+/* Default Control Pipe Maxpacket Size Register */
+/* Pipe Maxpacket Size Register */
+#define        DEVSEL          0xF000  /* b15-14: Device address select */
+#define        MAXP            0x007F  /* b6-0: Maxpacket size of default control pipe */
+
+/* Default Control Pipe Control Register */
+#define        BSTS            0x8000  /* b15: Buffer status */
+#define        SUREQ           0x4000  /* b14: Send USB request  */
+#define        CSCLR           0x2000  /* b13: complete-split status clear */
+#define        CSSTS           0x1000  /* b12: complete-split status */
+#define        SUREQCLR        0x0800  /* b11: stop setup request */
+#define        SQCLR           0x0100  /* b8: Sequence toggle bit clear */
+#define        SQSET           0x0080  /* b7: Sequence toggle bit set */
+#define        SQMON           0x0040  /* b6: Sequence toggle bit monitor */
+#define        PBUSY           0x0020  /* b5: pipe busy */
+#define        PINGE           0x0010  /* b4: ping enable */
+#define        CCPL            0x0004  /* b2: Enable control transfer complete */
+#define        PID             0x0003  /* b1-0: Response PID */
+#define          PID_STALL11    0x0003   /* STALL */
+#define          PID_STALL      0x0002   /* STALL */
+#define          PID_BUF        0x0001   /* BUF */
+#define          PID_NAK        0x0000   /* NAK */
+
+/* Pipe Window Select Register */
+#define        PIPENM          0x0007  /* b2-0: Pipe select */
+
+/* Pipe Configuration Register */
+#define        R8A66597_TYP    0xC000  /* b15-14: Transfer type */
+#define          R8A66597_ISO   0xC000           /* Isochronous */
+#define          R8A66597_INT   0x8000           /* Interrupt */
+#define          R8A66597_BULK  0x4000           /* Bulk */
+#define        R8A66597_BFRE   0x0400  /* b10: Buffer ready interrupt mode select */
+#define        R8A66597_DBLB   0x0200  /* b9: Double buffer mode select */
+#define        R8A66597_CNTMD  0x0100  /* b8: Continuous transfer mode select */
+#define        R8A66597_SHTNAK 0x0080  /* b7: Transfer end NAK */
+#define        R8A66597_DIR    0x0010  /* b4: Transfer direction select */
+#define        R8A66597_EPNUM  0x000F  /* b3-0: Eendpoint number select */
+
+/* Pipe Buffer Configuration Register */
+#define        BUFSIZE         0x7C00  /* b14-10: Pipe buffer size */
+#define        BUFNMB          0x007F  /* b6-0: Pipe buffer number */
+#define        PIPE0BUF        256
+#define        PIPExBUF        64
+
+/* Pipe Maxpacket Size Register */
+#define        MXPS            0x07FF  /* b10-0: Maxpacket size */
+
+/* Pipe Cycle Configuration Register */
+#define        IFIS            0x1000  /* b12: Isochronous in-buffer flush mode select */
+#define        IITV            0x0007  /* b2-0: Isochronous interval */
+
+/* Pipex Control Register */
+#define        BSTS            0x8000  /* b15: Buffer status */
+#define        INBUFM          0x4000  /* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define        CSCLR           0x2000  /* b13: complete-split status clear */
+#define        CSSTS           0x1000  /* b12: complete-split status */
+#define        ATREPM          0x0400  /* b10: Auto repeat mode */
+#define        ACLRM           0x0200  /* b9: Out buffer auto clear mode */
+#define        SQCLR           0x0100  /* b8: Sequence toggle bit clear */
+#define        SQSET           0x0080  /* b7: Sequence toggle bit set */
+#define        SQMON           0x0040  /* b6: Sequence toggle bit monitor */
+#define        PBUSY           0x0020  /* b5: pipe busy */
+#define        PID             0x0003  /* b1-0: Response PID */
+
+/* PIPExTRE */
+#define        TRENB           0x0200  /* b9: Transaction counter enable */
+#define        TRCLR           0x0100  /* b8: Transaction counter clear */
+
+/* PIPExTRN */
+#define        TRNCNT          0xFFFF  /* b15-0: Transaction counter */
+
+/* DEVADDx */
+#define        UPPHUB          0x7800
+#define        HUBPORT         0x0700
+#define        USBSPD          0x00C0
+#define        RTPORT          0x0001
+
+#define R8A66597_MAX_NUM_PIPE          10
+#define R8A66597_BUF_BSIZE             8
+#define R8A66597_MAX_DEVICE            10
+#define R8A66597_MAX_ROOT_HUB          2
+#define R8A66597_MAX_SAMPLING          10
+#define R8A66597_MAX_DMA_CHANNEL       2
+#define R8A66597_PIPE_NO_DMA           R8A66597_MAX_DMA_CHANNEL
+#define check_bulk_or_isoc(pipenum)    ((pipenum >= 1 && pipenum <= 5))
+#define check_interrupt(pipenum)       ((pipenum >= 6 && pipenum <= 9))
+#define make_devsel(addr)              (addr << 12)
+
+struct r8a66597_pipe_info {
+        u16 pipenum;
+        u16 address;   /* R8A66597 HCD usb addres */
+        u16 epnum;
+        u16 maxpacket;
+        u16 type;
+        u16 bufnum;
+        u16 buf_bsize;
+        u16 interval;
+        u16 dir_in;
+};
+
+struct r8a66597_pipe {
+       struct r8a66597_pipe_info info;
+
+       unsigned long fifoaddr;
+       unsigned long fifosel;
+       unsigned long fifoctr;
+       unsigned long pipectr;
+       unsigned long pipetre;
+       unsigned long pipetrn;
+};
+
+struct r8a66597_td {
+       struct r8a66597_pipe *pipe;
+       struct urb *urb;
+       struct list_head queue;
+
+       u16 type;
+       u16 pipenum;
+       int iso_cnt;
+
+       u16 address;            /* R8A66597's USB address */
+       u16 maxpacket;
+
+       unsigned zero_packet:1;
+       unsigned short_packet:1;
+       unsigned set_address:1;
+};
+
+struct r8a66597_device {
+       u16     address;        /* R8A66597's USB address */
+       u16     hub_port;
+       u16     root_port;
+
+       unsigned short ep_in_toggle;
+       unsigned short ep_out_toggle;
+       unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
+       unsigned char dma_map;
+
+       enum usb_device_state state;
+
+       struct usb_device *udev;
+       int usb_address;
+       struct list_head device_list;
+};
+
+struct r8a66597_root_hub {
+       u32 port;
+       u16 old_syssts;
+       int scount;
+
+       struct r8a66597_device  *dev;
+};
+
+struct r8a66597 {
+       spinlock_t lock;
+       unsigned long reg;
+
+       struct r8a66597_device          device0;
+       struct r8a66597_root_hub        root_hub[R8A66597_MAX_ROOT_HUB];
+       struct list_head                pipe_queue[R8A66597_MAX_NUM_PIPE];
+
+       struct timer_list rh_timer;
+       struct timer_list td_timer[R8A66597_MAX_NUM_PIPE];
+
+       unsigned short address_map;
+       unsigned short timeout_map;
+       unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
+       unsigned char dma_map;
+
+       struct list_head child_device;
+       unsigned long child_connect_map[4];
+};
+
+static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd)
+{
+       return (struct r8a66597 *)(hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *r8a66597_to_hcd(struct r8a66597 *r8a66597)
+{
+       return container_of((void *)r8a66597, struct usb_hcd, hcd_priv);
+}
+
+static inline struct r8a66597_td *r8a66597_get_td(struct r8a66597 *r8a66597,
+                                                 u16 pipenum)
+{
+       if (unlikely(list_empty(&r8a66597->pipe_queue[pipenum])))
+               return NULL;
+
+       return list_entry(r8a66597->pipe_queue[pipenum].next,
+                         struct r8a66597_td, queue);
+}
+
+static inline struct urb *r8a66597_get_urb(struct r8a66597 *r8a66597,
+                                          u16 pipenum)
+{
+       struct r8a66597_td *td;
+
+       td = r8a66597_get_td(r8a66597, pipenum);
+       return (td ? td->urb : NULL);
+}
+
+static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
+{
+       return inw(r8a66597->reg + offset);
+}
+
+static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
+                                     unsigned long offset, u16 *buf,
+                                     int len)
+{
+       len = (len + 1) / 2;
+       insw(r8a66597->reg + offset, buf, len);
+}
+
+static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
+                                 unsigned long offset)
+{
+       outw(val, r8a66597->reg + offset);
+}
+
+static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+                                      unsigned long offset, u16 *buf,
+                                      int len)
+{
+       unsigned long fifoaddr = r8a66597->reg + offset;
+       int odd = len & 0x0001;
+
+       len = len / 2;
+       outsw(fifoaddr, buf, len);
+       if (unlikely(odd)) {
+               buf = &buf[len];
+               outb((unsigned char)*buf, fifoaddr);
+       }
+}
+
+static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
+                                u16 val, u16 pat, unsigned long offset)
+{
+       u16 tmp;
+       tmp = r8a66597_read(r8a66597, offset);
+       tmp = tmp & (~pat);
+       tmp = tmp | val;
+       r8a66597_write(r8a66597, tmp, offset);
+}
+
+#define r8a66597_bclr(r8a66597, val, offset)   \
+                       r8a66597_mdfy(r8a66597, 0, val, offset)
+#define r8a66597_bset(r8a66597, val, offset)   \
+                       r8a66597_mdfy(r8a66597, val, 0, offset)
+
+static inline unsigned long get_syscfg_reg(int port)
+{
+       return port == 0 ? SYSCFG0 : SYSCFG1;
+}
+
+static inline unsigned long get_syssts_reg(int port)
+{
+       return port == 0 ? SYSSTS0 : SYSSTS1;
+}
+
+static inline unsigned long get_dvstctr_reg(int port)
+{
+       return port == 0 ? DVSTCTR0 : DVSTCTR1;
+}
+
+static inline unsigned long get_intenb_reg(int port)
+{
+       return port == 0 ? INTENB1 : INTENB2;
+}
+
+static inline unsigned long get_intsts_reg(int port)
+{
+       return port == 0 ? INTSTS1 : INTSTS2;
+}
+
+static inline u16 get_rh_usb_speed(struct r8a66597 *r8a66597, int port)
+{
+       unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+       return r8a66597_read(r8a66597, dvstctr_reg) & RHST;
+}
+
+static inline void r8a66597_port_power(struct r8a66597 *r8a66597, int port,
+                                      int power)
+{
+       unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+       if (power)
+               r8a66597_bset(r8a66597, VBOUT, dvstctr_reg);
+       else
+               r8a66597_bclr(r8a66597, VBOUT, dvstctr_reg);
+}
+
+#define get_pipectr_addr(pipenum)      (PIPE1CTR + (pipenum - 1) * 2)
+#define get_pipetre_addr(pipenum)      (PIPE1TRE + (pipenum - 1) * 4)
+#define get_pipetrn_addr(pipenum)      (PIPE1TRN + (pipenum - 1) * 4)
+#define get_devadd_addr(address)       (DEVADD0 + address * 2)
+
+#define enable_irq_ready(r8a66597, pipenum)    \
+       enable_pipe_irq(r8a66597, pipenum, BRDYENB)
+#define disable_irq_ready(r8a66597, pipenum)   \
+       disable_pipe_irq(r8a66597, pipenum, BRDYENB)
+#define enable_irq_empty(r8a66597, pipenum)    \
+       enable_pipe_irq(r8a66597, pipenum, BEMPENB)
+#define disable_irq_empty(r8a66597, pipenum)   \
+       disable_pipe_irq(r8a66597, pipenum, BEMPENB)
+#define enable_irq_nrdy(r8a66597, pipenum)     \
+       enable_pipe_irq(r8a66597, pipenum, NRDYENB)
+#define disable_irq_nrdy(r8a66597, pipenum)    \
+       disable_pipe_irq(r8a66597, pipenum, NRDYENB)
+
+#endif /* __R8A66597_H__ */
+
index d22da26ff1675d6a4f9f8e9a4b40520ff720d443..76c555a67dacc3931649d40f706f94ad2405dc68 100644 (file)
@@ -730,10 +730,9 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
        int rc = 0;
 
        spin_lock_irq(&uhci->lock);
-       if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
-               dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n");
+       if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
                rc = -ESHUTDOWN;
-       else if (!uhci->dead)
+       else if (!uhci->dead)
                wakeup_rh(uhci);
        spin_unlock_irq(&uhci->lock);
        return rc;
index 77145f9db0431e47c2cb861c836881a85b3d8740..d72c42e5f22d0a8f1434b9d36c864d177bd0c34a 100644 (file)
@@ -108,8 +108,6 @@ struct adu_device {
        struct urb*             interrupt_out_urb;
 };
 
-/* prevent races between open() and disconnect */
-static DEFINE_MUTEX(disconnect_mutex);
 static struct usb_driver adu_driver;
 
 static void adu_debug_data(int level, const char *function, int size,
@@ -256,8 +254,6 @@ static int adu_open(struct inode *inode, struct file *file)
 
        subminor = iminor(inode);
 
-       mutex_lock(&disconnect_mutex);
-
        interface = usb_find_interface(&adu_driver, subminor);
        if (!interface) {
                err("%s - error, can't find device for minor %d",
@@ -306,7 +302,6 @@ static int adu_open(struct inode *inode, struct file *file)
        up(&dev->sem);
 
 exit_no_device:
-       mutex_unlock(&disconnect_mutex);
        dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
 
        return retval;
@@ -318,12 +313,6 @@ static int adu_release_internal(struct adu_device *dev)
 
        dbg(2," %s : enter", __FUNCTION__);
 
-       if (dev->udev == NULL) {
-               /* the device was unplugged before the file was released */
-               adu_delete(dev);
-               goto exit;
-       }
-
        /* decrement our usage count for the device */
        --dev->open_count;
        dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
@@ -332,7 +321,6 @@ static int adu_release_internal(struct adu_device *dev)
                dev->open_count = 0;
        }
 
-exit:
        dbg(2," %s : leave", __FUNCTION__);
        return retval;
 }
@@ -367,8 +355,15 @@ static int adu_release(struct inode *inode, struct file *file)
                goto exit;
        }
 
-       /* do the work */
-       retval = adu_release_internal(dev);
+       if (dev->udev == NULL) {
+               /* the device was unplugged before the file was released */
+               up(&dev->sem);
+               adu_delete(dev);
+               dev = NULL;
+       } else {
+               /* do the work */
+               retval = adu_release_internal(dev);
+       }
 
 exit:
        if (dev)
@@ -831,19 +826,17 @@ static void adu_disconnect(struct usb_interface *interface)
 
        dbg(2," %s : enter", __FUNCTION__);
 
-       mutex_lock(&disconnect_mutex); /* not interruptible */
-
        dev = usb_get_intfdata(interface);
        usb_set_intfdata(interface, NULL);
 
-       down(&dev->sem); /* not interruptible */
-
        minor = dev->minor;
 
        /* give back our minor */
        usb_deregister_dev(interface, &adu_class);
        dev->minor = 0;
 
+       down(&dev->sem); /* not interruptible */
+
        /* if the device is not opened, then we clean up right now */
        dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
        if (!dev->open_count) {
@@ -854,8 +847,6 @@ static void adu_disconnect(struct usb_interface *interface)
                up(&dev->sem);
        }
 
-       mutex_unlock(&disconnect_mutex);
-
        dev_info(&interface->dev, "ADU device adutux%d now disconnected",
                 (minor - ADU_MINOR_BASE));
 
index cac1500cba62b8528faca6e1a370f8c769e2b1af..1fd5fc220cd7ee9ac81c08af66e10466e5bb3821 100644 (file)
@@ -2034,12 +2034,12 @@ static void auerswald_disconnect (struct usb_interface *intf)
        if (!cp)
                return;
 
-       down (&cp->mutex);
-       info ("device /dev/%s now disconnecting", cp->name);
-
        /* give back our USB minor number */
        usb_deregister_dev(intf, &auerswald_class);
 
+       down (&cp->mutex);
+       info ("device /dev/%s now disconnecting", cp->name);
+
        /* Stop the interrupt endpoint */
        auerswald_int_release (cp);
 
index b15f2fd8dab459b7ef4ea581f4192e7aae4c5c75..92c1d2768df9680afb7050d74b09b30c10db1d65 100644 (file)
 
 #define RIM_VENDOR             0x0fca
 #define BLACKBERRY             0x0001
+#define BLACKBERRY_PEARL_DUAL   0x0004
+#define BLACKBERRY_PEARL        0x0006
 
 static int debug;
+static int pearl_dual_mode = 1;
 
 #ifdef dbg
 #undef dbg
@@ -38,6 +41,8 @@ static int debug;
 
 static struct usb_device_id id_table [] = {
        { USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
+       { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL) },
+       { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL_DUAL) },
        { },                                    /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
@@ -86,6 +91,30 @@ static int magic_charge(struct usb_device *udev)
        return retval;
 }
 
+static int magic_dual_mode(struct usb_device *udev)
+{
+       char *dummy_buffer = kzalloc(2, GFP_KERNEL);
+       int retval;
+
+       if (!dummy_buffer)
+               return -ENOMEM;
+
+       /* send magic command so that the Blackberry Pearl device exposes
+        * two interfaces: both the USB mass-storage one and one which can
+        * be used for database access. */
+       dbg(&udev->dev, "Sending magic pearl command\n");
+       retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                                0xa9, 0xc0, 1, 1, dummy_buffer, 2, 100);
+       dbg(&udev->dev, "Magic pearl command returned %d\n", retval);
+
+       dbg(&udev->dev, "Calling set_configuration\n");
+       retval = usb_driver_set_configuration(udev, 1);
+       if (retval)
+               dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
+
+       return retval;
+}
+
 static int berry_probe(struct usb_interface *intf,
                       const struct usb_device_id *id)
 {
@@ -105,6 +134,10 @@ static int berry_probe(struct usb_interface *intf,
        /* turn the power on */
        magic_charge(udev);
 
+       if ((le16_to_cpu(udev->descriptor.idProduct) == BLACKBERRY_PEARL) &&
+           (pearl_dual_mode))
+               magic_dual_mode(udev);
+
        /* we don't really want to bind to the device, userspace programs can
         * handle the syncing just fine, so get outta here. */
        return -ENODEV;
@@ -138,3 +171,5 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
+module_param(pearl_dual_mode, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pearl_dual_mode, "Change Blackberry Pearl to run in dual mode");
index 8d0e360636e64e65ce5db737e9d23a892bf7b9f6..e6fd024024f50c1c317bba53328cd553bef7dd7b 100644 (file)
@@ -119,9 +119,6 @@ static struct usb_driver idmouse_driver = {
        .id_table = idmouse_table,
 };
 
-/* prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_mutex);
-
 static int idmouse_create_image(struct usb_idmouse *dev)
 {
        int bytes_read;
@@ -211,21 +208,15 @@ static int idmouse_open(struct inode *inode, struct file *file)
        struct usb_interface *interface;
        int result;
 
-       /* prevent disconnects */
-       mutex_lock(&disconnect_mutex);
-
        /* get the interface from minor number and driver information */
        interface = usb_find_interface (&idmouse_driver, iminor (inode));
-       if (!interface) {
-               mutex_unlock(&disconnect_mutex);
+       if (!interface)
                return -ENODEV;
-       }
+
        /* get the device information block from the interface */
        dev = usb_get_intfdata(interface);
-       if (!dev) {
-               mutex_unlock(&disconnect_mutex);
+       if (!dev)
                return -ENODEV;
-       }
 
        /* lock this device */
        down(&dev->sem);
@@ -255,9 +246,6 @@ error:
 
        /* unlock this device */
        up(&dev->sem);
-
-       /* unlock the disconnect semaphore */
-       mutex_unlock(&disconnect_mutex);
        return result;
 }
 
@@ -265,15 +253,10 @@ static int idmouse_release(struct inode *inode, struct file *file)
 {
        struct usb_idmouse *dev;
 
-       /* prevent a race condition with open() */
-       mutex_lock(&disconnect_mutex);
-
        dev = file->private_data;
 
-       if (dev == NULL) {
-               mutex_unlock(&disconnect_mutex);
+       if (dev == NULL)
                return -ENODEV;
-       }
 
        /* lock our device */
        down(&dev->sem);
@@ -281,7 +264,6 @@ static int idmouse_release(struct inode *inode, struct file *file)
        /* are we really open? */
        if (dev->open <= 0) {
                up(&dev->sem);
-               mutex_unlock(&disconnect_mutex);
                return -ENODEV;
        }
 
@@ -291,12 +273,9 @@ static int idmouse_release(struct inode *inode, struct file *file)
                /* the device was unplugged before the file was released */
                up(&dev->sem);
                idmouse_delete(dev);
-               mutex_unlock(&disconnect_mutex);
-               return 0;
+       } else {
+               up(&dev->sem);
        }
-
-       up(&dev->sem);
-       mutex_unlock(&disconnect_mutex);
        return 0;
 }
 
@@ -391,30 +370,27 @@ static void idmouse_disconnect(struct usb_interface *interface)
 {
        struct usb_idmouse *dev;
 
-       /* prevent races with open() */
-       mutex_lock(&disconnect_mutex);
-
        /* get device structure */
        dev = usb_get_intfdata(interface);
        usb_set_intfdata(interface, NULL);
 
-       /* lock it */
-       down(&dev->sem);
-
        /* give back our minor */
        usb_deregister_dev(interface, &idmouse_class);
 
+       /* lock it */
+       down(&dev->sem);
+
        /* prevent device read, write and ioctl */
        dev->present = 0;
 
-       /* unlock */
-       up(&dev->sem);
-
        /* if the device is opened, idmouse_release will clean this up */
-       if (!dev->open)
+       if (!dev->open) {
+               up(&dev->sem);
                idmouse_delete(dev);
-
-       mutex_unlock(&disconnect_mutex);
+       } else {
+               /* unlock */
+               up(&dev->sem);
+       }
 
        info("%s disconnected", DRIVER_DESC);
 }
index 3bb33f7bfa3626ee027218832d409e9dbc2cdb2a..28548d186712ab24872eb15be6d69c86452b8db9 100644 (file)
@@ -100,8 +100,6 @@ struct iowarrior {
 /*--------------*/
 /*    globals   */
 /*--------------*/
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX(disconnect_sem);
 
 /*
  *  USB spec identifies 5 second timeouts.
@@ -600,22 +598,18 @@ static int iowarrior_open(struct inode *inode, struct file *file)
 
        subminor = iminor(inode);
 
-       /* prevent disconnects */
-       down(&disconnect_sem);
-
        interface = usb_find_interface(&iowarrior_driver, subminor);
        if (!interface) {
                err("%s - error, can't find device for minor %d", __FUNCTION__,
                    subminor);
-               retval = -ENODEV;
-               goto out;
+               return -ENODEV;
        }
 
        dev = usb_get_intfdata(interface);
-       if (!dev) {
-               retval = -ENODEV;
-               goto out;
-       }
+       if (!dev)
+               return -ENODEV;
+
+       mutex_lock(&dev->mutex);
 
        /* Only one process can open each device, no sharing. */
        if (dev->opened) {
@@ -636,7 +630,7 @@ static int iowarrior_open(struct inode *inode, struct file *file)
        retval = 0;
 
 out:
-       up(&disconnect_sem);
+       mutex_unlock(&dev->mutex);
        return retval;
 }
 
@@ -868,19 +862,16 @@ static void iowarrior_disconnect(struct usb_interface *interface)
        struct iowarrior *dev;
        int minor;
 
-       /* prevent races with open() */
-       down(&disconnect_sem);
-
        dev = usb_get_intfdata(interface);
        usb_set_intfdata(interface, NULL);
 
-       mutex_lock(&dev->mutex);
-
        minor = dev->minor;
 
        /* give back our minor */
        usb_deregister_dev(interface, &iowarrior_class);
 
+       mutex_lock(&dev->mutex);
+
        /* prevent device read, write and ioctl */
        dev->present = 0;
 
@@ -898,7 +889,6 @@ static void iowarrior_disconnect(struct usb_interface *interface)
                /* no process is using the device, cleanup now */
                iowarrior_delete(dev);
        }
-       up(&disconnect_sem);
 
        dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
                 minor - IOWARRIOR_MINOR_BASE);
index 7bad494047621a38f61bd8cf90057f2d40870ea7..5e950b90c5414900fb1f7f8fe91a750660dda56d 100644 (file)
@@ -176,9 +176,6 @@ struct ld_usb {
        int                     interrupt_out_busy;
 };
 
-/* prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_mutex);
-
 static struct usb_driver ld_usb_driver;
 
 /**
@@ -298,35 +295,28 @@ static int ld_usb_open(struct inode *inode, struct file *file)
 {
        struct ld_usb *dev;
        int subminor;
-       int retval = 0;
+       int retval;
        struct usb_interface *interface;
 
        nonseekable_open(inode, file);
        subminor = iminor(inode);
 
-       mutex_lock(&disconnect_mutex);
-
        interface = usb_find_interface(&ld_usb_driver, subminor);
 
        if (!interface) {
                err("%s - error, can't find device for minor %d\n",
                     __FUNCTION__, subminor);
-               retval = -ENODEV;
-               goto unlock_disconnect_exit;
+               return -ENODEV;
        }
 
        dev = usb_get_intfdata(interface);
 
-       if (!dev) {
-               retval = -ENODEV;
-               goto unlock_disconnect_exit;
-       }
+       if (!dev)
+               return -ENODEV;
 
        /* lock this device */
-       if (down_interruptible(&dev->sem)) {
-               retval = -ERESTARTSYS;
-               goto unlock_disconnect_exit;
-       }
+       if (down_interruptible(&dev->sem))
+               return -ERESTARTSYS;
 
        /* allow opening only once */
        if (dev->open_count) {
@@ -366,9 +356,6 @@ static int ld_usb_open(struct inode *inode, struct file *file)
 unlock_exit:
        up(&dev->sem);
 
-unlock_disconnect_exit:
-       mutex_unlock(&disconnect_mutex);
-
        return retval;
 }
 
@@ -766,18 +753,16 @@ static void ld_usb_disconnect(struct usb_interface *intf)
        struct ld_usb *dev;
        int minor;
 
-       mutex_lock(&disconnect_mutex);
-
        dev = usb_get_intfdata(intf);
        usb_set_intfdata(intf, NULL);
 
-       down(&dev->sem);
-
        minor = intf->minor;
 
        /* give back our minor */
        usb_deregister_dev(intf, &ld_usb_class);
 
+       down(&dev->sem);
+
        /* if the device is not opened, then we clean up right now */
        if (!dev->open_count) {
                up(&dev->sem);
@@ -787,8 +772,6 @@ static void ld_usb_disconnect(struct usb_interface *intf)
                up(&dev->sem);
        }
 
-       mutex_unlock(&disconnect_mutex);
-
        dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",
                 (minor - USB_LD_MINOR_BASE));
 }
index 1713e19a789974b086fe96cd458136f37df5175f..2ed0daea894c8c93e5c7313d8dd6558634171095 100644 (file)
@@ -254,9 +254,6 @@ static int  tower_probe     (struct usb_interface *interface, const struct usb_devic
 static void tower_disconnect   (struct usb_interface *interface);
 
 
-/* prevent races between open() and disconnect */
-static DEFINE_MUTEX (disconnect_mutex);
-
 /* file operations needed when we register this driver */
 static const struct file_operations tower_fops = {
        .owner =        THIS_MODULE,
@@ -344,28 +341,26 @@ static int tower_open (struct inode *inode, struct file *file)
        nonseekable_open(inode, file);
        subminor = iminor(inode);
 
-       mutex_lock (&disconnect_mutex);
-
        interface = usb_find_interface (&tower_driver, subminor);
 
        if (!interface) {
                err ("%s - error, can't find device for minor %d",
                     __FUNCTION__, subminor);
                retval = -ENODEV;
-               goto unlock_disconnect_exit;
+               goto exit;
        }
 
        dev = usb_get_intfdata(interface);
 
        if (!dev) {
                retval = -ENODEV;
-               goto unlock_disconnect_exit;
+               goto exit;
        }
 
        /* lock this device */
        if (down_interruptible (&dev->sem)) {
                retval = -ERESTARTSYS;
-               goto unlock_disconnect_exit;
+               goto exit;
        }
 
        /* allow opening only once */
@@ -421,9 +416,7 @@ static int tower_open (struct inode *inode, struct file *file)
 unlock_exit:
        up (&dev->sem);
 
-unlock_disconnect_exit:
-       mutex_unlock (&disconnect_mutex);
-
+exit:
        dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
 
        return retval;
@@ -993,19 +986,16 @@ static void tower_disconnect (struct usb_interface *interface)
 
        dbg(2, "%s: enter", __FUNCTION__);
 
-       mutex_lock (&disconnect_mutex);
-
        dev = usb_get_intfdata (interface);
        usb_set_intfdata (interface, NULL);
 
-
-       down (&dev->sem);
-
        minor = dev->minor;
 
        /* give back our minor */
        usb_deregister_dev (interface, &tower_class);
 
+       down (&dev->sem);
+
        /* if the device is not opened, then we clean up right now */
        if (!dev->open_count) {
                up (&dev->sem);
@@ -1015,8 +1005,6 @@ static void tower_disconnect (struct usb_interface *interface)
                up (&dev->sem);
        }
 
-       mutex_unlock (&disconnect_mutex);
-
        info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
 
        dbg(2, "%s: leave", __FUNCTION__);
index 6f8b134a79cb8c89d495cb81ad75fc65401cdc39..9f37ba44c132d1cbbabb41f235b320dd155b92b3 100644 (file)
@@ -72,8 +72,6 @@ MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES
 
 static struct usb_driver sisusb_driver;
 
-DEFINE_MUTEX(disconnect_mutex);
-
 static void
 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
 {
@@ -2511,31 +2509,24 @@ sisusb_open(struct inode *inode, struct file *file)
        struct usb_interface *interface;
        int subminor = iminor(inode);
 
-       mutex_lock(&disconnect_mutex);
-
        if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
                printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
                                subminor);
-               mutex_unlock(&disconnect_mutex);
                return -ENODEV;
        }
 
-       if (!(sisusb = usb_get_intfdata(interface))) {
-               mutex_unlock(&disconnect_mutex);
+       if (!(sisusb = usb_get_intfdata(interface)))
                return -ENODEV;
-       }
 
        mutex_lock(&sisusb->lock);
 
        if (!sisusb->present || !sisusb->ready) {
                mutex_unlock(&sisusb->lock);
-               mutex_unlock(&disconnect_mutex);
                return -ENODEV;
        }
 
        if (sisusb->isopen) {
                mutex_unlock(&sisusb->lock);
-               mutex_unlock(&disconnect_mutex);
                return -EBUSY;
        }
 
@@ -2543,7 +2534,6 @@ sisusb_open(struct inode *inode, struct file *file)
                if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
                        if (sisusb_init_gfxdevice(sisusb, 0)) {
                                mutex_unlock(&sisusb->lock);
-                               mutex_unlock(&disconnect_mutex);
                                printk(KERN_ERR
                                        "sisusbvga[%d]: Failed to initialize "
                                        "device\n",
@@ -2552,7 +2542,6 @@ sisusb_open(struct inode *inode, struct file *file)
                        }
                } else {
                        mutex_unlock(&sisusb->lock);
-                       mutex_unlock(&disconnect_mutex);
                        printk(KERN_ERR
                                "sisusbvga[%d]: Device not attached to "
                                "USB 2.0 hub\n",
@@ -2570,8 +2559,6 @@ sisusb_open(struct inode *inode, struct file *file)
 
        mutex_unlock(&sisusb->lock);
 
-       mutex_unlock(&disconnect_mutex);
-
        return 0;
 }
 
@@ -2601,12 +2588,8 @@ sisusb_release(struct inode *inode, struct file *file)
        struct sisusb_usb_data *sisusb;
        int myminor;
 
-       mutex_lock(&disconnect_mutex);
-
-       if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
-               mutex_unlock(&disconnect_mutex);
+       if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
                return -ENODEV;
-       }
 
        mutex_lock(&sisusb->lock);
 
@@ -2626,8 +2609,6 @@ sisusb_release(struct inode *inode, struct file *file)
        /* decrement the usage count on our device */
        kref_put(&sisusb->kref, sisusb_delete);
 
-       mutex_unlock(&disconnect_mutex);
-
        return 0;
 }
 
@@ -3383,12 +3364,9 @@ static void sisusb_disconnect(struct usb_interface *intf)
        sisusb_console_exit(sisusb);
 #endif
 
-       /* The above code doesn't need the disconnect
-        * semaphore to be down; its meaning is to
-        * protect all other routines from the disconnect
-        * case, not the other way round.
-        */
-       mutex_lock(&disconnect_mutex);
+       minor = sisusb->minor;
+
+       usb_deregister_dev(intf, &usb_sisusb_class);
 
        mutex_lock(&sisusb->lock);
 
@@ -3396,12 +3374,8 @@ static void sisusb_disconnect(struct usb_interface *intf)
        if (!sisusb_wait_all_out_complete(sisusb))
                sisusb_kill_all_busy(sisusb);
 
-       minor = sisusb->minor;
-
        usb_set_intfdata(intf, NULL);
 
-       usb_deregister_dev(intf, &usb_sisusb_class);
-
 #ifdef SISUSB_OLD_CONFIG_COMPAT
        if (sisusb->ioctl32registered) {
                int ret;
@@ -3426,8 +3400,6 @@ static void sisusb_disconnect(struct usb_interface *intf)
        /* decrement our usage count */
        kref_put(&sisusb->kref, sisusb_delete);
 
-       mutex_unlock(&disconnect_mutex);
-
        printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
 }
 
index 5947afb0017ef49159d4b6558a1b740bd0160a83..8d0edc867f3316b969106dfb468d9f8bf249388b 100644 (file)
@@ -214,18 +214,13 @@ sisusbcon_init(struct vc_data *c, int init)
         * are set up/restored.
         */
 
-       mutex_lock(&disconnect_mutex);
-
-       if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
-               mutex_unlock(&disconnect_mutex);
+       if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
                return;
-       }
 
        mutex_lock(&sisusb->lock);
 
        if (!sisusb_sisusb_valid(sisusb)) {
                mutex_unlock(&sisusb->lock);
-               mutex_unlock(&disconnect_mutex);
                return;
        }
 
@@ -264,8 +259,6 @@ sisusbcon_init(struct vc_data *c, int init)
 
        mutex_unlock(&sisusb->lock);
 
-       mutex_unlock(&disconnect_mutex);
-
        if (init) {
                c->vc_cols = cols;
                c->vc_rows = rows;
@@ -284,12 +277,8 @@ sisusbcon_deinit(struct vc_data *c)
         * and others, ie not under our control.
         */
 
-       mutex_lock(&disconnect_mutex);
-
-       if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
-               mutex_unlock(&disconnect_mutex);
+       if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
                return;
-       }
 
        mutex_lock(&sisusb->lock);
 
@@ -314,8 +303,6 @@ sisusbcon_deinit(struct vc_data *c)
 
        /* decrement the usage count on our sisusb */
        kref_put(&sisusb->kref, sisusb_delete);
-
-       mutex_unlock(&disconnect_mutex);
 }
 
 /* interface routine */
@@ -1490,14 +1477,11 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
 {
        int i, ret, minor = sisusb->minor;
 
-       mutex_lock(&disconnect_mutex);
-
        mutex_lock(&sisusb->lock);
 
        /* Erm.. that should not happen */
        if (sisusb->haveconsole || !sisusb->SiS_Pr) {
                mutex_unlock(&sisusb->lock);
-               mutex_unlock(&disconnect_mutex);
                return 1;
        }
 
@@ -1508,14 +1492,12 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
            first > MAX_NR_CONSOLES ||
            last > MAX_NR_CONSOLES) {
                mutex_unlock(&sisusb->lock);
-               mutex_unlock(&disconnect_mutex);
                return 1;
        }
 
        /* If gfxcore not initialized or no consoles given, quit graciously */
        if (!sisusb->gfxinit || first < 1 || last < 1) {
                mutex_unlock(&sisusb->lock);
-               mutex_unlock(&disconnect_mutex);
                return 0;
        }
 
@@ -1526,7 +1508,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
        /* Set up text mode (and upload  default font) */
        if (sisusb_reset_text_mode(sisusb, 1)) {
                mutex_unlock(&sisusb->lock);
-               mutex_unlock(&disconnect_mutex);
                printk(KERN_ERR
                        "sisusbvga[%d]: Failed to set up text mode\n",
                        minor);
@@ -1550,7 +1531,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
        /* Allocate screen buffer */
        if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
                mutex_unlock(&sisusb->lock);
-               mutex_unlock(&disconnect_mutex);
                printk(KERN_ERR
                        "sisusbvga[%d]: Failed to allocate screen buffer\n",
                        minor);
@@ -1558,7 +1538,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
        }
 
        mutex_unlock(&sisusb->lock);
-       mutex_unlock(&disconnect_mutex);
 
        /* Now grab the desired console(s) */
        ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
index f05f83268af41df9ccce52a6d99e244d819b4cc1..864bc0e96591afcedfe351342964041c6fee833d 100644 (file)
@@ -808,8 +808,6 @@ static const struct SiS_VCLKData SiSUSB_VCLKData[] =
        { 0x2b,0xc2, 35}  /* 0x71 768@576@60 */
 };
 
-extern struct mutex disconnect_mutex;
-
 int            SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 int            SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
 
index 12bad8a205a75cc9fc8d8e7f2b4e55b3d092ebc7..504f7221b0d095e8847b902cc6e8955c6517172f 100644 (file)
@@ -45,13 +45,13 @@ struct usb_lcd {
        struct kref             kref;
        struct semaphore        limit_sem;              /* to stop writes at full throttle from
                                                         * using up all RAM */
+       struct usb_anchor       submitted;              /* URBs to wait for before suspend */
 };
 #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
 
 #define USB_LCD_CONCURRENT_WRITES      5
 
 static struct usb_driver lcd_driver;
-static DEFINE_MUTEX(usb_lcd_open_mutex);
 
 
 static void lcd_delete(struct kref *kref)
@@ -68,35 +68,35 @@ static int lcd_open(struct inode *inode, struct file *file)
 {
        struct usb_lcd *dev;
        struct usb_interface *interface;
-       int subminor;
-       int retval = 0;
+       int subminor, r;
 
        subminor = iminor(inode);
 
-       mutex_lock(&usb_lcd_open_mutex);
        interface = usb_find_interface(&lcd_driver, subminor);
        if (!interface) {
                err ("USBLCD: %s - error, can't find device for minor %d",
                     __FUNCTION__, subminor);
-               retval = -ENODEV;
-               goto exit;
+               return -ENODEV;
        }
 
        dev = usb_get_intfdata(interface);
-       if (!dev) {
-               retval = -ENODEV;
-               goto exit;
-       }
+       if (!dev)
+               return -ENODEV;
 
        /* increment our usage count for the device */
        kref_get(&dev->kref);
 
+       /* grab a power reference */
+       r = usb_autopm_get_interface(interface);
+       if (r < 0) {
+               kref_put(&dev->kref, lcd_delete);
+               return r;
+       }
+
        /* save our object in the file's private structure */
        file->private_data = dev;
 
-exit:
-       mutex_unlock(&usb_lcd_open_mutex);
-       return retval;
+       return 0;
 }
 
 static int lcd_release(struct inode *inode, struct file *file)
@@ -108,6 +108,7 @@ static int lcd_release(struct inode *inode, struct file *file)
                return -ENODEV;
 
        /* decrement the count on our device */
+       usb_autopm_put_interface(dev->interface);
        kref_put(&dev->kref, lcd_delete);
        return 0;
 }
@@ -233,12 +234,14 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
                          usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
                          buf, count, lcd_write_bulk_callback, dev);
        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       usb_anchor_urb(urb, &dev->submitted);
        
        /* send the data out the bulk port */
        retval = usb_submit_urb(urb, GFP_KERNEL);
        if (retval) {
                err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval);
-               goto error;
+               goto error_unanchor;
        }
        
        /* release our reference to this urb, the USB core will eventually free it entirely */
@@ -246,7 +249,8 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
 
 exit:
        return count;
-
+error_unanchor:
+       usb_unanchor_urb(urb);
 error:
        usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
        usb_free_urb(urb);
@@ -291,6 +295,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
        }
        kref_init(&dev->kref);
        sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES);
+       init_usb_anchor(&dev->submitted);
 
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
        dev->interface = interface;
@@ -358,22 +363,41 @@ error:
        return retval;
 }
 
+static void lcd_draw_down(struct usb_lcd *dev)
+{
+       int time;
+
+       time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
+       if (!time)
+               usb_kill_anchored_urbs(&dev->submitted);
+}
+
+static int lcd_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct usb_lcd *dev = usb_get_intfdata(intf);
+
+       if (!dev)
+               return 0;
+       lcd_draw_down(dev);
+       return 0;
+}
+
+static int lcd_resume (struct usb_interface *intf)
+{
+       return 0;
+}
+
 static void lcd_disconnect(struct usb_interface *interface)
 {
        struct usb_lcd *dev;
         int minor = interface->minor;
 
-        /* prevent skel_open() from racing skel_disconnect() */
-        mutex_lock(&usb_lcd_open_mutex);
-
         dev = usb_get_intfdata(interface);
         usb_set_intfdata(interface, NULL);
 
         /* give back our minor */
         usb_deregister_dev(interface, &lcd_class);
  
-       mutex_unlock(&usb_lcd_open_mutex);
-
        /* decrement our usage count */
        kref_put(&dev->kref, lcd_delete);
 
@@ -384,7 +408,10 @@ static struct usb_driver lcd_driver = {
        .name =         "usblcd",
        .probe =        lcd_probe,
        .disconnect =   lcd_disconnect,
+       .suspend =      lcd_suspend,
+       .resume =       lcd_resume,
        .id_table =     id_table,
+       .supports_autosuspend = 1,
 };
 
 static int __init usb_lcd_init(void)
index 0af11a66207cf3e88bb151f2e067c024c5eeea46..c03dfd7a9d36f8fe460869158d78f2a599e1f28e 100644 (file)
@@ -4,7 +4,7 @@
  * This is a binary format reader.
  *
  * Copyright (C) 2006 Paolo Abeni (paolo.abeni@email.it)
- * Copyright (C) 2006 Pete Zaitcev (zaitcev@redhat.com)
+ * Copyright (C) 2006,2007 Pete Zaitcev (zaitcev@redhat.com)
  */
 
 #include <linux/kernel.h>
@@ -172,6 +172,7 @@ static inline struct mon_bin_hdr *MON_OFF2HDR(const struct mon_reader_bin *rp,
 
 #define MON_RING_EMPTY(rp)     ((rp)->b_cnt == 0)
 
+static struct class *mon_bin_class;
 static dev_t mon_bin_dev0;
 static struct cdev mon_bin_cdev;
 
@@ -1144,10 +1145,38 @@ static void mon_free_buff(struct mon_pgmap *map, int npages)
                free_page((unsigned long) map[n].ptr);
 }
 
+int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
+{
+       struct device *dev;
+       unsigned minor = ubus? ubus->busnum: 0;
+
+       if (minor >= MON_BIN_MAX_MINOR)
+               return 0;
+
+       dev = device_create(mon_bin_class, ubus? ubus->controller: NULL,
+                       MKDEV(MAJOR(mon_bin_dev0), minor), "usbmon%d", minor);
+       if (IS_ERR(dev))
+               return 0;
+
+       mbus->classdev = dev;
+       return 1;
+}
+
+void mon_bin_del(struct mon_bus *mbus)
+{
+       device_destroy(mon_bin_class, mbus->classdev->devt);
+}
+
 int __init mon_bin_init(void)
 {
        int rc;
 
+       mon_bin_class = class_create(THIS_MODULE, "usbmon");
+       if (IS_ERR(mon_bin_class)) {
+               rc = PTR_ERR(mon_bin_class);
+               goto err_class;
+       }
+
        rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon");
        if (rc < 0)
                goto err_dev;
@@ -1164,6 +1193,8 @@ int __init mon_bin_init(void)
 err_add:
        unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
 err_dev:
+       class_destroy(mon_bin_class);
+err_class:
        return rc;
 }
 
@@ -1171,4 +1202,5 @@ void mon_bin_exit(void)
 {
        cdev_del(&mon_bin_cdev);
        unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
+       class_destroy(mon_bin_class);
 }
index 8977ec0d0f9928218ada7a44fdb62cfd142aa072..ce61d8b0fd866b4ea91346296d828667d30a9468 100644 (file)
@@ -220,6 +220,8 @@ static void mon_bus_remove(struct usb_bus *ubus)
        list_del(&mbus->bus_link);
        if (mbus->text_inited)
                mon_text_del(mbus);
+       if (mbus->bin_inited)
+               mon_bin_del(mbus);
 
        mon_dissolve(mbus, ubus);
        kref_put(&mbus->ref, mon_bus_drop);
@@ -301,8 +303,8 @@ static void mon_bus_init(struct usb_bus *ubus)
        mbus->u_bus = ubus;
        ubus->mon_bus = mbus;
 
-       mbus->text_inited = mon_text_add(mbus, ubus->busnum);
-       // mon_bin_add(...)
+       mbus->text_inited = mon_text_add(mbus, ubus);
+       mbus->bin_inited = mon_bin_add(mbus, ubus);
 
        mutex_lock(&mon_lock);
        list_add_tail(&mbus->bus_link, &mon_buses);
@@ -321,8 +323,8 @@ static void mon_bus0_init(void)
        spin_lock_init(&mbus->lock);
        INIT_LIST_HEAD(&mbus->r_list);
 
-       mbus->text_inited = mon_text_add(mbus, 0);
-       // mbus->bin_inited = mon_bin_add(mbus, 0);
+       mbus->text_inited = mon_text_add(mbus, NULL);
+       mbus->bin_inited = mon_bin_add(mbus, NULL);
 }
 
 /*
@@ -403,6 +405,8 @@ static void __exit mon_exit(void)
 
                if (mbus->text_inited)
                        mon_text_del(mbus);
+               if (mbus->bin_inited)
+                       mon_bin_del(mbus);
 
                /*
                 * This never happens, because the open/close paths in
@@ -423,6 +427,8 @@ static void __exit mon_exit(void)
        mbus = &mon_bus0;
        if (mbus->text_inited)
                mon_text_del(mbus);
+       if (mbus->bin_inited)
+               mon_bin_del(mbus);
 
        mutex_unlock(&mon_lock);
 
index ec0cc51e39acc42b0576b15c99bced374228fc2e..982b773d71e69f186210322e98c434ba78425d21 100644 (file)
@@ -655,20 +655,24 @@ static const struct file_operations mon_fops_text_u = {
        .release =      mon_text_release,
 };
 
-int mon_text_add(struct mon_bus *mbus, int busnum)
+int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
 {
        struct dentry *d;
        enum { NAMESZ = 10 };
        char name[NAMESZ];
+       int busnum = ubus? ubus->busnum: 0;
        int rc;
 
-       rc = snprintf(name, NAMESZ, "%dt", busnum);
-       if (rc <= 0 || rc >= NAMESZ)
-               goto err_print_t;
-       d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_t);
-       if (d == NULL)
-               goto err_create_t;
-       mbus->dent_t = d;
+       if (ubus != NULL) {
+               rc = snprintf(name, NAMESZ, "%dt", busnum);
+               if (rc <= 0 || rc >= NAMESZ)
+                       goto err_print_t;
+               d = debugfs_create_file(name, 0600, mon_dir, mbus,
+                                                            &mon_fops_text_t);
+               if (d == NULL)
+                       goto err_create_t;
+               mbus->dent_t = d;
+       }
 
        rc = snprintf(name, NAMESZ, "%du", busnum);
        if (rc <= 0 || rc >= NAMESZ)
@@ -694,8 +698,10 @@ err_print_s:
        mbus->dent_u = NULL;
 err_create_u:
 err_print_u:
-       debugfs_remove(mbus->dent_t);
-       mbus->dent_t = NULL;
+       if (ubus != NULL) {
+               debugfs_remove(mbus->dent_t);
+               mbus->dent_t = NULL;
+       }
 err_create_t:
 err_print_t:
        return 0;
@@ -704,7 +710,8 @@ err_print_t:
 void mon_text_del(struct mon_bus *mbus)
 {
        debugfs_remove(mbus->dent_u);
-       debugfs_remove(mbus->dent_t);
+       if (mbus->dent_t != NULL)
+               debugfs_remove(mbus->dent_t);
        debugfs_remove(mbus->dent_s);
 }
 
index 13d63255283e8682e2c4fe032f80be2dcc5248fa..f68ad6d99ad7563581919fb024c37a4c5259a6e7 100644 (file)
@@ -20,9 +20,11 @@ struct mon_bus {
        struct usb_bus *u_bus;
 
        int text_inited;
+       int bin_inited;
        struct dentry *dent_s;          /* Debugging file */
        struct dentry *dent_t;          /* Text interface file */
        struct dentry *dent_u;          /* Second text interface file */
+       struct device *classdev;        /* Device in usbmon class */
 
        /* Ref */
        int nreaders;                   /* Under mon_lock AND mbus->lock */
@@ -52,9 +54,10 @@ void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r);
 
 struct mon_bus *mon_bus_lookup(unsigned int num);
 
-int /*bool*/ mon_text_add(struct mon_bus *mbus, int busnum);
+int /*bool*/ mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus);
 void mon_text_del(struct mon_bus *mbus);
-// void mon_bin_add(struct mon_bus *);
+int /*bool*/ mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus);
+void mon_bin_del(struct mon_bus *mbus);
 
 int __init mon_text_init(void);
 void mon_text_exit(void);
index 3efe67092f15b85c1db4c4a145b83a79270789e6..43d6db696f905cc7361cee823ccb60d2ed99d4d6 100644 (file)
@@ -464,6 +464,16 @@ config USB_SERIAL_PL2303
          To compile this driver as a module, choose M here: the
          module will be called pl2303.
 
+config USB_SERIAL_OTI6858
+       tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller (EXPERIMENTAL)"
+       depends on USB_SERIAL
+       help
+         Say Y here if you want to use the OTi-6858 single port USB to serial
+          converter device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called oti6858.
+
 config USB_SERIAL_HP4X
         tristate "USB HP4x Calculators support"
         depends on USB_SERIAL
index 61166ad450e607f97a1f68b13ce1e398ea3a9b94..07a976eca6b7eed0e2a81c6f6724c7db2c9a5544 100644 (file)
@@ -40,6 +40,7 @@ obj-$(CONFIG_USB_SERIAL_MOS7840)              += mos7840.o
 obj-$(CONFIG_USB_SERIAL_NAVMAN)                        += navman.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)               += omninet.o
 obj-$(CONFIG_USB_SERIAL_OPTION)                        += option.o
+obj-$(CONFIG_USB_SERIAL_OTI6858)               += oti6858.o
 obj-$(CONFIG_USB_SERIAL_PL2303)                        += pl2303.o
 obj-$(CONFIG_USB_SERIAL_SAFE)                  += safe_serial.o
 obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS)                += sierra.o
index fbc8c27d5d994763b842a718d8df2406a62881e7..1cd29cd6bd00c46f524db37a8f21da42be9598f9 100644 (file)
@@ -411,12 +411,13 @@ static int aircable_write(struct usb_serial_port *port,
 static void aircable_write_bulk_callback(struct urb *urb)
 {
        struct usb_serial_port *port = urb->context;
+       int status = urb->status;
        int result;
 
-       dbg("%s - urb->status: %d", __FUNCTION__ , urb->status);
+       dbg("%s - urb status: %d", __FUNCTION__ , status);
 
        /* This has been taken from cypress_m8.c cypress_write_int_callback */
-       switch (urb->status) {
+       switch (status) {
                case 0:
                        /* success */
                        break;
@@ -425,14 +426,14 @@ static void aircable_write_bulk_callback(struct urb *urb)
                case -ESHUTDOWN:
                        /* this urb is terminated, clean up */
                        dbg("%s - urb shutting down with status: %d",
-                           __FUNCTION__, urb->status);
+                           __FUNCTION__, status);
                        port->write_urb_busy = 0;
                        return;
                default:
                        /* error in the urb, so we have to resubmit it */
                        dbg("%s - Overflow in write", __FUNCTION__);
                        dbg("%s - nonzero write bulk status received: %d",
-                           __FUNCTION__, urb->status);
+                           __FUNCTION__, status);
                        port->write_urb->transfer_buffer_length = 1;
                        port->write_urb->dev = port->serial->dev;
                        result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
@@ -457,16 +458,17 @@ static void aircable_read_bulk_callback(struct urb *urb)
        unsigned long no_packages, remaining, package_length, i;
        int result, shift = 0;
        unsigned char *temp;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - urb status = %d", __FUNCTION__, status);
                if (!port->open_count) {
                        dbg("%s - port is closed, exiting.", __FUNCTION__);
                        return;
                }
-               if (urb->status == -EPROTO) {
+               if (status == -EPROTO) {
                        dbg("%s - caught -EPROTO, resubmitting the urb",
                            __FUNCTION__);
                        usb_fill_bulk_urb(port->read_urb, port->serial->dev,
index 39a49836259405605eb041f847e248d63a1728b8..cff6fd190a28273869c4f9b1203e75ccee1ccc85 100644 (file)
@@ -82,12 +82,13 @@ static void airprime_read_bulk_callback(struct urb *urb)
        unsigned char *data = urb->transfer_buffer;
        struct tty_struct *tty;
        int result;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
+       if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, urb->status);
+                   __FUNCTION__, status);
                return;
        }
        usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
@@ -109,6 +110,7 @@ static void airprime_write_bulk_callback(struct urb *urb)
 {
        struct usb_serial_port *port = urb->context;
        struct airprime_private *priv = usb_get_serial_port_data(port);
+       int status = urb->status;
        unsigned long flags;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
@@ -116,9 +118,9 @@ static void airprime_write_bulk_callback(struct urb *urb)
        /* free up the transfer buffer, as usb_free_urb() does not do this */
        kfree (urb->transfer_buffer);
 
-       if (urb->status)
+       if (status)
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, urb->status);
+                   __FUNCTION__, status);
        spin_lock_irqsave(&priv->lock, flags);
        --priv->outstanding_urbs;
        spin_unlock_irqrestore(&priv->lock, flags);
index fe437125f14bc9f86cdb2b4352c04c2c2528aca6..c9fd486c1c7d7a030b9d5b039caabe2a9f3f5c56 100644 (file)
@@ -172,7 +172,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if ((!port->tty) || (!port->tty->termios)) {
+       if (!port->tty || !port->tty->termios) {
                dbg("%s - no tty structures", __FUNCTION__);
                return;
        }
@@ -188,16 +188,6 @@ static void ark3116_set_termios(struct usb_serial_port *port,
 
        cflag = port->tty->termios->c_cflag;
 
-       /* check that they really want us to change something: */
-       if (old_termios) {
-               if ((cflag == old_termios->c_cflag) &&
-                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
-                    RELEVANT_IFLAG(old_termios->c_iflag))) {
-                       dbg("%s - nothing to change...", __FUNCTION__);
-                       return;
-               }
-       }
-
        buf = kmalloc(1, GFP_KERNEL);
        if (!buf) {
                dbg("error kmalloc");
@@ -220,7 +210,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
                        dbg("setting CS7");
                        break;
                default:
-                       err("CSIZE was set but not CS5-CS8, using CS8!");
+                       dbg("CSIZE was set but not CS5-CS8, using CS8!");
                        /* fall through */
                case CS8:
                        config |= 0x03;
@@ -251,38 +241,33 @@ static void ark3116_set_termios(struct usb_serial_port *port,
        }
 
        /* set baudrate */
-       baud = 0;
-       switch (cflag & CBAUD) {
-               case B0:
-                       err("can't set 0 baud, using 9600 instead");
+       baud = tty_get_baud_rate(port->tty);
+
+       switch (baud) {
+               case 75:
+               case 150:
+               case 300:
+               case 600:
+               case 1200:
+               case 1800:
+               case 2400:
+               case 4800:
+               case 9600:
+               case 19200:
+               case 38400:
+               case 57600:
+               case 115200:
+               case 230400:
+               case 460800:
                        break;
-               case B75:       baud = 75;      break;
-               case B150:      baud = 150;     break;
-               case B300:      baud = 300;     break;
-               case B600:      baud = 600;     break;
-               case B1200:     baud = 1200;    break;
-               case B1800:     baud = 1800;    break;
-               case B2400:     baud = 2400;    break;
-               case B4800:     baud = 4800;    break;
-               case B9600:     baud = 9600;    break;
-               case B19200:    baud = 19200;   break;
-               case B38400:    baud = 38400;   break;
-               case B57600:    baud = 57600;   break;
-               case B115200:   baud = 115200;  break;
-               case B230400:   baud = 230400;  break;
-               case B460800:   baud = 460800;  break;
+               /* set 9600 as default (if given baudrate is invalid for example) */
                default:
-                       dbg("does not support the baudrate requested (fix it)");
-                       break;
+                       baud = 9600;
        }
 
-       /* set 9600 as default (if given baudrate is invalid for example) */
-       if (baud == 0)
-               baud = 9600;
-
        /*
         * found by try'n'error, be careful, maybe there are other options
-        * for multiplicator etc!
+        * for multiplicator etc! (3.5 for example)
         */
        if (baud == 460800)
                /* strange, for 460800 the formula is wrong
index 3b800d277c4b90849a693d8092b421d297eadd82..e67ce25f7512627dad57bf4930d2ca26c6bc413a 100644 (file)
@@ -255,9 +255,10 @@ static void belkin_sa_read_int_callback (struct urb *urb)
        struct belkin_sa_private *priv;
        unsigned char *data = urb->transfer_buffer;
        int retval;
+       int status = urb->status;
        unsigned long flags;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -265,10 +266,12 @@ static void belkin_sa_read_int_callback (struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d",
+                   __FUNCTION__, status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d",
+                   __FUNCTION__, status);
                goto exit;
        }
 
@@ -346,6 +349,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
        unsigned long flags;
        unsigned long control_state;
        int bad_flow_control;
+       speed_t baud;
        
        if ((!port->tty) || (!port->tty->termios)) {
                dbg ("%s - no tty or termios structure", __FUNCTION__);
@@ -361,16 +365,8 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
        bad_flow_control = priv->bad_flow_control;
        spin_unlock_irqrestore(&priv->lock, flags);
        
-       /* check that they really want us to change something */
-       if (old_termios) {
-               if ((cflag == old_termios->c_cflag) &&
-                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-                       dbg("%s - nothing to change...", __FUNCTION__);
-                       return;
-               }
-               old_iflag = old_termios->c_iflag;
-               old_cflag = old_termios->c_cflag;
-       }
+       old_iflag = old_termios->c_iflag;
+       old_cflag = old_termios->c_cflag;
 
        /* Set the baud rate */
        if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
@@ -384,38 +380,30 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
                                if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0)
                                        err("Set RTS error");
                }
+       }
 
-               switch(cflag & CBAUD) {
-                       case B0: /* handled below */ break;
-                       case B300: urb_value = BELKIN_SA_BAUD(300); break;
-                       case B600: urb_value = BELKIN_SA_BAUD(600); break;
-                       case B1200: urb_value = BELKIN_SA_BAUD(1200); break;
-                       case B2400: urb_value = BELKIN_SA_BAUD(2400); break;
-                       case B4800: urb_value = BELKIN_SA_BAUD(4800); break;
-                       case B9600: urb_value = BELKIN_SA_BAUD(9600); break;
-                       case B19200: urb_value = BELKIN_SA_BAUD(19200); break;
-                       case B38400: urb_value = BELKIN_SA_BAUD(38400); break;
-                       case B57600: urb_value = BELKIN_SA_BAUD(57600); break;
-                       case B115200: urb_value = BELKIN_SA_BAUD(115200); break;
-                       case B230400: urb_value = BELKIN_SA_BAUD(230400); break;
-                       default: err("BELKIN USB Serial Adapter: unsupported baudrate request, using default of 9600");
-                               urb_value = BELKIN_SA_BAUD(9600); break;
-               }
-               if ((cflag & CBAUD) != B0 ) {
-                       if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
-                               err("Set baudrate error");
-               } else {
-                       /* Disable flow control */
-                       if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0)
-                               err("Disable flowcontrol error");
-
-                       /* Drop RTS and DTR */
-                       control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-                       if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
-                               err("DTR LOW error");
-                       if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0)
-                               err("RTS LOW error");
-               }
+       baud = tty_get_baud_rate(port->tty);
+       urb_value = BELKIN_SA_BAUD(baud);
+       /* Clip to maximum speed */
+       if (urb_value == 0)
+               urb_value = 1;
+       /* Turn it back into a resulting real baud rate */
+       baud = BELKIN_SA_BAUD(urb_value);
+       /* FIXME: Once the tty updates are done then push this back to the tty */
+
+       if ((cflag & CBAUD) != B0 ) {
+               if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
+                       err("Set baudrate error");
+       } else {
+               /* Disable flow control */
+               if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0)
+                       err("Disable flowcontrol error");
+               /* Drop RTS and DTR */
+               control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+               if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
+                       err("DTR LOW error");
+               if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0)
+                       err("RTS LOW error");
        }
 
        /* set the parity */
@@ -435,7 +423,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
                        case CS6: urb_value = BELKIN_SA_DATA_BITS(6); break;
                        case CS7: urb_value = BELKIN_SA_DATA_BITS(7); break;
                        case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break;
-                       default: err("CSIZE was not CS5-CS8, using default of 8");
+                       default: dbg("CSIZE was not CS5-CS8, using default of 8");
                                urb_value = BELKIN_SA_DATA_BITS(8);
                                break;
                }
index 4167753ed31fc3efa401bb1366c4e1991e04358b..4353df92487f528256ca27bb8169d287d3f85b63 100644 (file)
@@ -305,12 +305,13 @@ static void cyberjack_read_int_callback( struct urb *urb )
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct cyberjack_private *priv = usb_get_serial_port_data(port);
        unsigned char *data = urb->transfer_buffer;
+       int status = urb->status;
        int result;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
        /* the urb might have been killed. */
-       if (urb->status)
+       if (status)
                return;
 
        usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
@@ -365,12 +366,14 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
        unsigned char *data = urb->transfer_buffer;
        short todo;
        int result;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
-       
+
        usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
@@ -411,12 +414,14 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct cyberjack_private *priv = usb_get_serial_port_data(port);
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
        port->write_urb_busy = 0;
-       if (urb->status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
index 57b8e27285fc007dda4805d0447d51fb0096e43a..163386336a5daa76852eda408974ace308bf2176 100644 (file)
@@ -1275,10 +1275,11 @@ static void cypress_read_int_callback(struct urb *urb)
        int bytes = 0;
        int result;
        int i = 0;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       switch (urb->status) {
+       switch (status) {
        case 0: /* success */
                break;
        case -ECONNRESET:
@@ -1292,7 +1293,7 @@ static void cypress_read_int_callback(struct urb *urb)
        default:
                /* something ugly is going on... */
                dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
-                       __FUNCTION__,urb->status);
+                       __FUNCTION__, status);
                cypress_set_dead(port);
                return;
        }
@@ -1419,10 +1420,11 @@ static void cypress_write_int_callback(struct urb *urb)
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct cypress_private *priv = usb_get_serial_port_data(port);
        int result;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
-       
-       switch (urb->status) {
+
+       switch (status) {
                case 0:
                        /* success */
                        break;
@@ -1430,7 +1432,8 @@ static void cypress_write_int_callback(struct urb *urb)
                case -ENOENT:
                case -ESHUTDOWN:
                        /* this urb is terminated, clean up */
-                       dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+                       dbg("%s - urb shutting down with status: %d",
+                           __FUNCTION__, status);
                        priv->write_urb_in_use = 0;
                        return;
                case -EPIPE: /* no break needed; clear halt and resubmit */
@@ -1438,7 +1441,8 @@ static void cypress_write_int_callback(struct urb *urb)
                                break;
                        usb_clear_halt(port->serial->dev, 0x02);
                        /* error in the urb, so we have to resubmit it */
-                       dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+                       dbg("%s - nonzero write bulk status received: %d",
+                           __FUNCTION__, status);
                        port->interrupt_out_urb->transfer_buffer_length = 1;
                        port->interrupt_out_urb->dev = port->serial->dev;
                        result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
@@ -1450,7 +1454,7 @@ static void cypress_write_int_callback(struct urb *urb)
                        break;
                default:
                        dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
-                               __FUNCTION__,urb->status);
+                               __FUNCTION__, status);
                        cypress_set_dead(port);
                        break;
        }
index d78692c01cfa3ca9a75749ee9a3fec6f5e92762f..976f54ec26e66e0529f10a2c6d6879953a1b7f67 100644 (file)
@@ -416,9 +416,6 @@ struct digi_port {
        int dp_port_num;
        int dp_out_buf_len;
        unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];
-       int dp_in_buf_len;
-       unsigned char dp_in_buf[DIGI_IN_BUF_SIZE];
-       unsigned char dp_in_flag_buf[DIGI_IN_BUF_SIZE];
        int dp_write_urb_in_use;
        unsigned int dp_modem_signals;
        wait_queue_head_t dp_modem_change_wait;
@@ -920,7 +917,6 @@ dbg( "digi_rx_throttle: TOP: port=%d", priv->dp_port_num );
        spin_lock_irqsave( &priv->dp_port_lock, flags );
        priv->dp_throttled = 1;
        priv->dp_throttle_restart = 0;
-       priv->dp_in_buf_len = 0;
        spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
 }
@@ -930,23 +926,16 @@ static void digi_rx_unthrottle( struct usb_serial_port *port )
 {
 
        int ret = 0;
-       int len;
        unsigned long flags;
        struct digi_port *priv = usb_get_serial_port_data(port);
-       struct tty_struct *tty = port->tty;
-
 
 dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
 
        spin_lock_irqsave( &priv->dp_port_lock, flags );
 
-       /* send any buffered chars from throttle time on to tty subsystem */
-
-       len = tty_buffer_request_room(tty, priv->dp_in_buf_len);
-       if( len > 0 ) {
-               tty_insert_flip_string_flags(tty, priv->dp_in_buf, priv->dp_in_flag_buf, len);
-               tty_flip_buffer_push( tty );
-       }
+       /* turn throttle off */
+       priv->dp_throttled = 0;
+       priv->dp_throttle_restart = 0;
 
        /* restart read chain */
        if( priv->dp_throttle_restart ) {
@@ -954,11 +943,6 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
                ret = usb_submit_urb( port->read_urb, GFP_ATOMIC );
        }
 
-       /* turn throttle off */
-       priv->dp_throttled = 0;
-       priv->dp_in_buf_len = 0;
-       priv->dp_throttle_restart = 0;
-
        spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
        if( ret ) {
@@ -1340,19 +1324,21 @@ static void digi_write_bulk_callback( struct urb *urb )
        struct digi_port *priv;
        struct digi_serial *serial_priv;
        int ret = 0;
+       int status = urb->status;
 
 
-dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status );
+       dbg("digi_write_bulk_callback: TOP, urb status=%d", status);
 
        /* port and serial sanity check */
        if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) {
-               err("%s: port or port->private is NULL, status=%d", __FUNCTION__,
-                       urb->status );
+               err("%s: port or port->private is NULL, status=%d",
+                   __FUNCTION__, status);
                return;
        }
        serial = port->serial;
        if( serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL ) {
-               err("%s: serial or serial->private is NULL, status=%d", __FUNCTION__, urb->status );
+               err("%s: serial or serial->private is NULL, status=%d",
+                   __FUNCTION__, status);
                return;
        }
 
@@ -1687,7 +1673,6 @@ dbg( "digi_startup: TOP" );
                spin_lock_init( &priv->dp_port_lock );
                priv->dp_port_num = i;
                priv->dp_out_buf_len = 0;
-               priv->dp_in_buf_len = 0;
                priv->dp_write_urb_in_use = 0;
                priv->dp_modem_signals = 0;
                init_waitqueue_head( &priv->dp_modem_change_wait );
@@ -1757,25 +1742,28 @@ static void digi_read_bulk_callback( struct urb *urb )
        struct digi_port *priv;
        struct digi_serial *serial_priv;
        int ret;
+       int status = urb->status;
 
 
 dbg( "digi_read_bulk_callback: TOP" );
 
        /* port sanity check, do not resubmit if port is not valid */
        if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) {
-               err("%s: port or port->private is NULL, status=%d", __FUNCTION__,
-                       urb->status );
+               err("%s: port or port->private is NULL, status=%d",
+                   __FUNCTION__, status);
                return;
        }
        if( port->serial == NULL
        || (serial_priv=usb_get_serial_data(port->serial)) == NULL ) {
-               err("%s: serial is bad or serial->private is NULL, status=%d", __FUNCTION__, urb->status );
+               err("%s: serial is bad or serial->private is NULL, status=%d",
+                   __FUNCTION__, status);
                return;
        }
 
        /* do not resubmit urb if it has any status error */
-       if( urb->status ) {
-               err("%s: nonzero read bulk status: status=%d, port=%d", __FUNCTION__, urb->status, priv->dp_port_num );
+       if (status) {
+               err("%s: nonzero read bulk status: status=%d, port=%d",
+                   __FUNCTION__, status, priv->dp_port_num);
                return;
        }
 
@@ -1816,10 +1804,11 @@ static int digi_read_inb_callback( struct urb *urb )
        struct digi_port *priv = usb_get_serial_port_data(port);
        int opcode = ((unsigned char *)urb->transfer_buffer)[0];
        int len = ((unsigned char *)urb->transfer_buffer)[1];
-       int status = ((unsigned char *)urb->transfer_buffer)[2];
+       int port_status = ((unsigned char *)urb->transfer_buffer)[2];
        unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
        int flag,throttled;
        int i;
+       int status = urb->status;
 
        /* do not process callbacks on closed ports */
        /* but do continue the read chain */
@@ -1828,7 +1817,10 @@ static int digi_read_inb_callback( struct urb *urb )
 
        /* short/multiple packet check */
        if( urb->actual_length != len + 2 ) {
-               err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", __FUNCTION__, urb->status, priv->dp_port_num, opcode, len, urb->actual_length, status );
+               err("%s: INCOMPLETE OR MULTIPLE PACKET, urb status=%d, "
+                   "port=%d, opcode=%d, len=%d, actual_length=%d, "
+                   "port_status=%d", __FUNCTION__, status, priv->dp_port_num,
+                   opcode, len, urb->actual_length, port_status);
                return( -1 );
        }
 
@@ -1843,52 +1835,37 @@ static int digi_read_inb_callback( struct urb *urb )
        /* receive data */
        if( opcode == DIGI_CMD_RECEIVE_DATA ) {
 
-               /* get flag from status */
+               /* get flag from port_status */
                flag = 0;
 
                /* overrun is special, not associated with a char */
-               if( status & DIGI_OVERRUN_ERROR ) {
+               if (port_status & DIGI_OVERRUN_ERROR) {
                        tty_insert_flip_char( tty, 0, TTY_OVERRUN );
                }
 
                /* break takes precedence over parity, */
                /* which takes precedence over framing errors */
-               if( status & DIGI_BREAK_ERROR ) {
+               if (port_status & DIGI_BREAK_ERROR) {
                        flag = TTY_BREAK;
-               } else if( status & DIGI_PARITY_ERROR ) {
+               } else if (port_status & DIGI_PARITY_ERROR) {
                        flag = TTY_PARITY;
-               } else if( status & DIGI_FRAMING_ERROR ) {
+               } else if (port_status & DIGI_FRAMING_ERROR) {
                        flag = TTY_FRAME;
                }
 
-               /* data length is len-1 (one byte of len is status) */
+               /* data length is len-1 (one byte of len is port_status) */
                --len;
 
-               if( throttled ) {
-
-                       len = min( len,
-                               DIGI_IN_BUF_SIZE - priv->dp_in_buf_len );
-
-                       if( len > 0 ) {
-                               memcpy( priv->dp_in_buf + priv->dp_in_buf_len,
-                                       data, len );
-                               memset( priv->dp_in_flag_buf
-                                       + priv->dp_in_buf_len, flag, len );
-                               priv->dp_in_buf_len += len;
-                       }
-
-               } else {
-                       len = tty_buffer_request_room(tty, len);
-                       if( len > 0 ) {
-                               /* Hot path */
-                               if(flag == TTY_NORMAL)
-                                       tty_insert_flip_string(tty, data, len);
-                               else {
-                                       for(i = 0; i < len; i++)
-                                               tty_insert_flip_char(tty, data[i], flag);
-                               }
-                               tty_flip_buffer_push( tty );
+               len = tty_buffer_request_room(tty, len);
+               if( len > 0 ) {
+                       /* Hot path */
+                       if(flag == TTY_NORMAL)
+                               tty_insert_flip_string(tty, data, len);
+                       else {
+                               for(i = 0; i < len; i++)
+                                       tty_insert_flip_char(tty, data[i], flag);
                        }
+                       tty_flip_buffer_push( tty );
                }
        }
 
index 4703c8f853837431616249f846647d07b344546b..050fcc996f5600d2984b6c84c2b4b71d61ecb70d 100644 (file)
@@ -326,12 +326,14 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port)
 
 static void empeg_write_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
@@ -345,11 +347,13 @@ static void empeg_read_bulk_callback (struct urb *urb)
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
        int result;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
index da1c6f7f82b8123aba7e089c4133b5f7beace4f0..7b1673a440775aaef3673915432cbed74c508051 100644 (file)
@@ -271,26 +271,58 @@ static int debug;
 static __u16 vendor = FTDI_VID;
 static __u16 product;
 
+struct ftdi_private {
+       ftdi_chip_type_t chip_type;
+                               /* type of the device, either SIO or FT8U232AM */
+       int baud_base;          /* baud base clock for divisor setting */
+       int custom_divisor;     /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
+       __u16 last_set_data_urb_value ;
+                               /* the last data state set - needed for doing a break */
+        int write_offset;       /* This is the offset in the usb data block to write the serial data -
+                                * it is different between devices
+                                */
+       int flags;              /* some ASYNC_xxxx flags are supported */
+       unsigned long last_dtr_rts;     /* saved modem control outputs */
+        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+       char prev_status, diff_status;        /* Used for TIOCMIWAIT */
+       __u8 rx_flags;          /* receive state flags (throttling) */
+       spinlock_t rx_lock;     /* spinlock for receive state */
+       struct delayed_work rx_work;
+       struct usb_serial_port *port;
+       int rx_processed;
+       unsigned long rx_bytes;
+
+       __u16 interface;        /* FT2232C port interface (0 for FT232/245) */
+
+       int force_baud;         /* if non-zero, force the baud rate to this value */
+       int force_rtscts;       /* if non-zero, force RTS-CTS to always be enabled */
+
+       spinlock_t tx_lock;     /* spinlock for transmit state */
+       unsigned long tx_bytes;
+       unsigned long tx_outstanding_bytes;
+       unsigned long tx_outstanding_urbs;
+};
+
 /* struct ftdi_sio_quirk is used by devices requiring special attention. */
 struct ftdi_sio_quirk {
        int (*probe)(struct usb_serial *);
-       void (*setup)(struct usb_serial *); /* Special settings during startup. */
+       void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */
 };
 
 static int   ftdi_olimex_probe         (struct usb_serial *serial);
-static void  ftdi_USB_UIRT_setup       (struct usb_serial *serial);
-static void  ftdi_HE_TIRA1_setup       (struct usb_serial *serial);
+static void  ftdi_USB_UIRT_setup       (struct ftdi_private *priv);
+static void  ftdi_HE_TIRA1_setup       (struct ftdi_private *priv);
 
 static struct ftdi_sio_quirk ftdi_olimex_quirk = {
        .probe  = ftdi_olimex_probe,
 };
 
 static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
-       .setup = ftdi_USB_UIRT_setup,
+       .port_probe = ftdi_USB_UIRT_setup,
 };
 
 static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
-       .setup = ftdi_HE_TIRA1_setup,
+       .port_probe = ftdi_HE_TIRA1_setup,
 };
 
 /*
@@ -567,38 +599,6 @@ static const char *ftdi_chip_name[] = {
 #define THROTTLED              0x01
 #define ACTUALLY_THROTTLED     0x02
 
-struct ftdi_private {
-       ftdi_chip_type_t chip_type;
-                               /* type of the device, either SIO or FT8U232AM */
-       int baud_base;          /* baud base clock for divisor setting */
-       int custom_divisor;     /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
-       __u16 last_set_data_urb_value ;
-                               /* the last data state set - needed for doing a break */
-        int write_offset;       /* This is the offset in the usb data block to write the serial data -
-                                * it is different between devices
-                                */
-       int flags;              /* some ASYNC_xxxx flags are supported */
-       unsigned long last_dtr_rts;     /* saved modem control outputs */
-        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
-       char prev_status, diff_status;        /* Used for TIOCMIWAIT */
-       __u8 rx_flags;          /* receive state flags (throttling) */
-       spinlock_t rx_lock;     /* spinlock for receive state */
-       struct delayed_work rx_work;
-       struct usb_serial_port *port;
-       int rx_processed;
-       unsigned long rx_bytes;
-
-       __u16 interface;        /* FT2232C port interface (0 for FT232/245) */
-
-       int force_baud;         /* if non-zero, force the baud rate to this value */
-       int force_rtscts;       /* if non-zero, force RTS-CTS to always be enabled */
-
-       spinlock_t tx_lock;     /* spinlock for transmit state */
-       unsigned long tx_bytes;
-       unsigned long tx_outstanding_bytes;
-       unsigned long tx_outstanding_urbs;
-};
-
 /* Used for TIOCMIWAIT */
 #define FTDI_STATUS_B0_MASK    (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
 #define FTDI_STATUS_B1_MASK    (FTDI_RS_BI)
@@ -609,7 +609,6 @@ struct ftdi_private {
 
 /* function prototypes for a FTDI serial converter */
 static int  ftdi_sio_probe     (struct usb_serial *serial, const struct usb_device_id *id);
-static int  ftdi_sio_attach            (struct usb_serial *serial);
 static void ftdi_shutdown              (struct usb_serial *serial);
 static int  ftdi_sio_port_probe        (struct usb_serial_port *port);
 static int  ftdi_sio_port_remove       (struct usb_serial_port *port);
@@ -663,7 +662,6 @@ static struct usb_serial_driver ftdi_sio_device = {
        .ioctl =                ftdi_ioctl,
        .set_termios =          ftdi_set_termios,
        .break_ctl =            ftdi_break_ctl,
-       .attach =               ftdi_sio_attach,
        .shutdown =             ftdi_shutdown,
 };
 
@@ -1149,7 +1147,9 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
                dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
                retval = device_create_file(&port->dev, &dev_attr_event_char);
                if ((!retval) &&
-                   (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) {
+                   (priv->chip_type == FT232BM ||
+                    priv->chip_type == FT2232C ||
+                    priv->chip_type == FT232RL)) {
                        retval = device_create_file(&port->dev,
                                                    &dev_attr_latency_timer);
                }
@@ -1198,6 +1198,8 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id
 static int ftdi_sio_port_probe(struct usb_serial_port *port)
 {
        struct ftdi_private *priv;
+       struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
+
 
        dbg("%s",__FUNCTION__);
 
@@ -1214,6 +1216,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
           than queue a task to deliver them */
        priv->flags = ASYNC_LOW_LATENCY;
 
+       if (quirk && quirk->port_probe)
+               quirk->port_probe(priv);
+
        /* Increase the size of read buffers */
        kfree(port->bulk_in_buffer);
        port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL);
@@ -1244,29 +1249,13 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
        return 0;
 }
 
-/* attach subroutine */
-static int ftdi_sio_attach (struct usb_serial *serial)
-{
-       /* Check for device requiring special set up. */
-       struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial);
-
-       if (quirk && quirk->setup)
-               quirk->setup(serial);
-
-       return 0;
-} /* ftdi_sio_attach */
-
-
 /* Setup for the USB-UIRT device, which requires hardwired
  * baudrate (38400 gets mapped to 312500) */
 /* Called from usbserial:serial_probe */
-static void ftdi_USB_UIRT_setup (struct usb_serial *serial)
+static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
 {
-       struct ftdi_private *priv;
-
        dbg("%s",__FUNCTION__);
 
-       priv = usb_get_serial_port_data(serial->port[0]);
        priv->flags |= ASYNC_SPD_CUST;
        priv->custom_divisor = 77;
        priv->force_baud = B38400;
@@ -1274,13 +1263,10 @@ static void ftdi_USB_UIRT_setup (struct usb_serial *serial)
 
 /* Setup for the HE-TIRA1 device, which requires hardwired
  * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled.  */
-static void ftdi_HE_TIRA1_setup (struct usb_serial *serial)
+static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
 {
-       struct ftdi_private *priv;
-
        dbg("%s",__FUNCTION__);
 
-       priv = usb_get_serial_port_data(serial->port[0]);
        priv->flags |= ASYNC_SPD_CUST;
        priv->custom_divisor = 240;
        priv->force_baud = B38400;
@@ -1574,14 +1560,15 @@ static void ftdi_write_bulk_callback (struct urb *urb)
        struct ftdi_private *priv;
        int data_offset;       /* will be 1 for the SIO and 0 otherwise */
        unsigned long countback;
+       int status = urb->status;
 
        /* free up the transfer buffer, as usb_free_urb() does not do this */
        kfree (urb->transfer_buffer);
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("nonzero write bulk status received: %d", urb->status);
+       if (status) {
+               dbg("nonzero write bulk status received: %d", status);
                return;
        }
 
@@ -1657,6 +1644,7 @@ static void ftdi_read_bulk_callback (struct urb *urb)
        struct ftdi_private *priv;
        unsigned long countread;
        unsigned long flags;
+       int status = urb->status;
 
        if (urb->number_of_packets > 0) {
                err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__,
@@ -1685,9 +1673,10 @@ static void ftdi_read_bulk_callback (struct urb *urb)
                err("%s - Not my urb!", __FUNCTION__);
        }
 
-       if (urb->status) {
+       if (status) {
                /* This will happen at close every time so it is a dbg not an err */
-               dbg("(this is ok on close) nonzero read bulk status received: %d", urb->status);
+               dbg("(this is ok on close) nonzero read bulk status received: "
+                   "%d", status);
                return;
        }
 
index 74660a3aa6708f3221738b8acea686af4313a80f..04bd3b7a298516a4f4409033df182ddfaf54ea80 100644 (file)
@@ -1036,15 +1036,16 @@ static void garmin_write_bulk_callback (struct urb *urb)
        unsigned long flags;
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+       int status = urb->status;
 
        /* free up the transfer buffer, as usb_free_urb() does not do this */
        kfree (urb->transfer_buffer);
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
+       if (status) {
                dbg("%s - nonzero write bulk status received: %d",
-                       __FUNCTION__, urb->status);
+                       __FUNCTION__, status);
                spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
                spin_unlock_irqrestore(&garmin_data_p->lock, flags);
@@ -1281,7 +1282,8 @@ static void garmin_read_bulk_callback (struct urb *urb)
        struct usb_serial *serial =  port->serial;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        unsigned char *data = urb->transfer_buffer;
-       int status;
+       int status = urb->status;
+       int retval;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -1290,9 +1292,9 @@ static void garmin_read_bulk_callback (struct urb *urb)
                return;
        }
 
-       if (urb->status) {
+       if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                       __FUNCTION__, urb->status);
+                       __FUNCTION__, status);
                return;
        }
 
@@ -1306,19 +1308,19 @@ static void garmin_read_bulk_callback (struct urb *urb)
                spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART;
                spin_unlock_irqrestore(&garmin_data_p->lock, flags);
-               status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-               if (status)
+               retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+               if (retval)
                        dev_err(&port->dev,
                                "%s - failed resubmitting read urb, error %d\n",
-                               __FUNCTION__, status);
+                               __FUNCTION__, retval);
        } else if (urb->actual_length > 0) {
                /* Continue trying to read until nothing more is received  */
                if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) {
-                       status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-                       if (status)
+                       retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+                       if (retval)
                                dev_err(&port->dev,
-                                       "%s - failed resubmitting read urb, error %d\n",
-                                       __FUNCTION__, status);
+                                       "%s - failed resubmitting read urb, "
+                                       "error %d\n", __FUNCTION__, retval);
                }
        } else {
                dbg("%s - end of bulk data", __FUNCTION__);
@@ -1333,13 +1335,14 @@ static void garmin_read_bulk_callback (struct urb *urb)
 static void garmin_read_int_callback (struct urb *urb)
 {
        unsigned long flags;
-       int status;
+       int retval;
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct usb_serial *serial = port->serial;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        unsigned char *data = urb->transfer_buffer;
+       int status = urb->status;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -1348,11 +1351,11 @@ static void garmin_read_int_callback (struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                       __FUNCTION__, urb->status);
+                       __FUNCTION__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                       __FUNCTION__, urb->status);
+                       __FUNCTION__, status);
                return;
        }
 
@@ -1374,11 +1377,11 @@ static void garmin_read_int_callback (struct urb *urb)
                                        port->read_urb->transfer_buffer,
                                        port->read_urb->transfer_buffer_length,
                                        garmin_read_bulk_callback, port);
-                       status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-                       if (status) {
+                       retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+                       if (retval) {
                                dev_err(&port->dev,
                                        "%s - failed submitting read urb, error %d\n",
-                               __FUNCTION__, status);
+                               __FUNCTION__, retval);
                        } else {
                                spin_lock_irqsave(&garmin_data_p->lock, flags);
                                garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
@@ -1422,11 +1425,11 @@ static void garmin_read_int_callback (struct urb *urb)
        }
 
        port->interrupt_in_urb->dev = port->serial->dev;
-       status = usb_submit_urb (urb, GFP_ATOMIC);
-       if (status)
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval)
                dev_err(&urb->dev->dev,
                        "%s - Error %d submitting interrupt urb\n",
-                       __FUNCTION__, status);
+                       __FUNCTION__, retval);
 }
 
 
index 4f8282ad77208b66e4c406f826100cb300b5247a..88a2c7dce335f9b1cde151ae457bf1d55054132d 100644 (file)
@@ -69,6 +69,7 @@ struct usb_serial_driver usb_serial_generic_device = {
        .shutdown =             usb_serial_generic_shutdown,
        .throttle =             usb_serial_generic_throttle,
        .unthrottle =           usb_serial_generic_unthrottle,
+       .resume =               usb_serial_generic_resume,
 };
 
 static int generic_probe(struct usb_interface *interface,
@@ -169,6 +170,23 @@ static void generic_cleanup (struct usb_serial_port *port)
        }
 }
 
+int usb_serial_generic_resume(struct usb_serial *serial)
+{
+       struct usb_serial_port *port;
+       int i, c = 0, r;
+
+       for (i = 0; i < serial->num_ports; i++) {
+               port = serial->port[i];
+               if (port->open_count && port->read_urb) {
+                       r = usb_submit_urb(port->read_urb, GFP_NOIO);
+                       if (r < 0)
+                               c++;
+               }
+       }
+
+       return c ? -EIO : 0;
+}
+
 void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
 {
        dbg("%s - port %d", __FUNCTION__, port->number);
@@ -263,79 +281,82 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
        return (chars);
 }
 
-/* Push data to tty layer and resubmit the bulk read URB */
-static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+
+static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
 {
-       struct usb_serial *serial = port->serial;
        struct urb *urb = port->read_urb;
-       struct tty_struct *tty = port->tty;
+       struct usb_serial *serial = port->serial;
        int result;
 
-       /* Push data to tty */
-       if (tty && urb->actual_length) {
-               tty_buffer_request_room(tty, urb->actual_length);
-               tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length);
-               tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
-       }
-
        /* Continue reading from device */
-       usb_fill_bulk_urb (port->read_urb, serial->dev,
+       usb_fill_bulk_urb (urb, serial->dev,
                           usb_rcvbulkpipe (serial->dev,
                                            port->bulk_in_endpointAddress),
-                          port->read_urb->transfer_buffer,
-                          port->read_urb->transfer_buffer_length,
+                          urb->transfer_buffer,
+                          urb->transfer_buffer_length,
                           ((serial->type->read_bulk_callback) ? 
                             serial->type->read_bulk_callback : 
                             usb_serial_generic_read_bulk_callback), port);
-       result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+       result = usb_submit_urb(urb, mem_flags);
        if (result)
                dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
 }
 
+/* Push data to tty layer and resubmit the bulk read URB */
+static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+{
+       struct urb *urb = port->read_urb;
+       struct tty_struct *tty = port->tty;
+       int room;
+
+       /* Push data to tty */
+       if (tty && urb->actual_length) {
+               room = tty_buffer_request_room(tty, urb->actual_length);
+               if (room) {
+                       tty_insert_flip_string(tty, urb->transfer_buffer, room);
+                       tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
+               }
+       }
+
+       resubmit_read_urb(port, GFP_ATOMIC);
+}
+
 void usb_serial_generic_read_bulk_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        unsigned char *data = urb->transfer_buffer;
-       int is_throttled;
-       unsigned long flags;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+       if (unlikely(status != 0)) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
        usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
 
        /* Throttle the device if requested by tty */
-       if (urb->actual_length) {
-               spin_lock_irqsave(&port->lock, flags);
-               is_throttled = port->throttled = port->throttle_req;
-               spin_unlock_irqrestore(&port->lock, flags);
-               if (is_throttled) {
-                       /* Let the received data linger in the read URB;
-                        * usb_serial_generic_unthrottle() will pick it
-                        * up later. */
-                       dbg("%s - throttling device", __FUNCTION__);
-                       return;
-               }
-       }
-
-       /* Handle data and continue reading from device */
-       flush_and_resubmit_read_urb(port);
+       spin_lock(&port->lock);
+       if (!(port->throttled = port->throttle_req))
+               /* Handle data and continue reading from device */
+               flush_and_resubmit_read_urb(port);
+       spin_unlock(&port->lock);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 
 void usb_serial_generic_write_bulk_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
        port->write_urb_busy = 0;
-       if (urb->status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
@@ -370,8 +391,8 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port)
        spin_unlock_irqrestore(&port->lock, flags);
 
        if (was_throttled) {
-               /* Handle pending data and resume reading from device */
-               flush_and_resubmit_read_urb(port);
+               /* Resume reading from device */
+               resubmit_read_urb(port, GFP_KERNEL);
        }
 }
 
index 056e1923c4de16134bb15b96c9f23e3c694809f6..dd42f57089ffea3a97ee86357113079d00a972a9 100644 (file)
@@ -599,10 +599,11 @@ static void edge_interrupt_callback (struct urb *urb)
        int txCredits;
        int portNumber;
        int result;
+       int status = urb->status;
 
        dbg("%s", __FUNCTION__);
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -610,10 +611,12 @@ static void edge_interrupt_callback (struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d",
+                   __FUNCTION__, status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d",
+                   __FUNCTION__, status);
                goto exit;
        }
 
@@ -688,13 +691,15 @@ static void edge_bulk_in_callback (struct urb *urb)
 {
        struct edgeport_serial  *edge_serial = (struct edgeport_serial *)urb->context;
        unsigned char           *data = urb->transfer_buffer;
-       int                     status;
+       int                     retval;
        __u16                   raw_data_length;
+       int status = urb->status;
 
        dbg("%s", __FUNCTION__);
 
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __FUNCTION__, status);
                edge_serial->read_in_progress = false;
                return;
        }
@@ -722,9 +727,11 @@ static void edge_bulk_in_callback (struct urb *urb)
        if (edge_serial->rxBytesAvail > 0) {
                dbg("%s - posting a read", __FUNCTION__);
                edge_serial->read_urb->dev = edge_serial->serial->dev;
-               status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
-               if (status) {
-                       dev_err(&urb->dev->dev, "%s - usb_submit_urb(read bulk) failed, status = %d\n", __FUNCTION__, status);
+               retval = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
+               if (retval) {
+                       dev_err(&urb->dev->dev,
+                               "%s - usb_submit_urb(read bulk) failed, "
+                               "retval = %d\n", __FUNCTION__, retval);
                        edge_serial->read_in_progress = false;
                }
        } else {
@@ -744,11 +751,13 @@ static void edge_bulk_out_data_callback (struct urb *urb)
 {
        struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
        struct tty_struct *tty;
+       int status = urb->status;
 
        dbg("%s", __FUNCTION__);
 
-       if (urb->status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, status);
        }
 
        tty = edge_port->port->tty;
@@ -1504,15 +1513,6 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
        }
 
        cflag = tty->termios->c_cflag;
-       /* check that they really want us to change something */
-       if (old_termios) {
-               if (cflag == old_termios->c_cflag &&
-                   tty->termios->c_iflag == old_termios->c_iflag) {
-                       dbg("%s - nothing to change", __FUNCTION__);
-                       return;
-               }
-       }
-
        dbg("%s - clfag %08x iflag %08x", __FUNCTION__, 
            tty->termios->c_cflag, tty->termios->c_iflag);
        if (old_termios) {
index 93b56d68a27b9c009edfefdbc8b82955399eee57..4496b068c50f4597da1897240508f18b5a6c9008 100644 (file)
@@ -5,7 +5,7 @@
 //**************************************************************
 
 
-static int IMAGE_SIZE = 12749;
+static int IMAGE_SIZE = 12938;
 
 struct EDGE_FIRMWARE_VERSION_INFO
 {
@@ -16,7 +16,7 @@ struct EDGE_FIRMWARE_VERSION_INFO
 
 static struct EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME =
 {
-       4, 10, 0                // Major, Minor, Build
+       4, 80, 0                // Major, Minor, Build
 
 };
 
@@ -27,16 +27,16 @@ static unsigned char IMAGE_ARRAY_NAME[] =
 //      WORD    Length;
 //      BYTE    CheckSum;
 //  };
-0xca, 0x31, 
-0xa8, 
+0x87, 0x32,
+0x9a,
 
-0x02, 0x26, 0xfe, 0x02, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 
+0x02, 0x27, 0xbf, 0x02, 0x21, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x3f, 
 0x8c, 0x85, 0x40, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3e, 
 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x3e, 0x75, 
 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x8c, 0xe5, 0x81, 
-0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x94, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, 
+0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0xdc, 0xe6, 0xf0, 0x08, 0xa3, 0xd9,
 0xfa, 0x74, 0x08, 0x25, 0x3e, 0xf8, 0x05, 0x3e, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x3e, 
 0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x3e, 0x00, 0x80, 0xef, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0x86, 
 0x81, 0xe5, 0x3e, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 
@@ -49,387 +49,398 @@ static unsigned char IMAGE_ARRAY_NAME[] =
 0xc9, 0xf0, 0x69, 0x60, 0x02, 0x7e, 0x04, 0xa3, 0xe0, 0xca, 0xf0, 0x6a, 0x60, 0x02, 0x7e, 0x04, 
 0xa3, 0xe0, 0xcb, 0xf0, 0x6b, 0x60, 0x02, 0x7e, 0x04, 0x22, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 
 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 
-0xc0, 0x06, 0xc0, 0x07, 0x90, 0xff, 0x93, 0x74, 0x01, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, 
-0x02, 0x11, 0x94, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xaf, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 
-0x83, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, 
-0x90, 0xff, 0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 
-0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, 
-0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 
-0xa3, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, 
-0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25, 
-0xb4, 0x02, 0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, 
-0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 
-0x80, 0x03, 0x02, 0x02, 0x62, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04, 
-0xf1, 0x20, 0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 
-0x14, 0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 
-0x7e, 0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x33, 0x12, 0x00, 0xc9, 0xee, 
-0x64, 0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 
-0x02, 0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x33, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 
-0x33, 0x7c, 0x0a, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 
-0xa3, 0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 
-0x80, 0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 
-0xd2, 0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 
-0x60, 0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d, 
-0x60, 0x13, 0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 
-0x0f, 0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 
-0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 
-0x90, 0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 
-0xec, 0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 
-0x01, 0x7f, 0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 
-0xff, 0xea, 0x90, 0xfa, 0xba, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0x30, 0xe4, 0xf5, 0x4d, 0xe5, 
-0x4d, 0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0x11, 0xe4, 0x12, 0x1a, 0x38, 0x05, 0x4d, 0x04, 
-0x12, 0x1c, 0x02, 0x80, 0xea, 0x12, 0x1c, 0x30, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 
-0xc0, 0x70, 0x03, 0x02, 0x08, 0xc5, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 
-0xe0, 0xfe, 0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 
-0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0x4c, 0x03, 0x56, 0x00, 0x04, 0x29, 0x01, 0x05, 0x3c, 0x03, 
-0x06, 0x03, 0x05, 0x06, 0x45, 0x06, 0x07, 0xa7, 0x08, 0x07, 0xef, 0x09, 0x08, 0x4b, 0x0a, 0x08, 
-0x8b, 0x0b, 0x00, 0x00, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
-0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x02, 0x45, 
-0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 
-0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x11, 0x74, 
-0x01, 0x12, 0x1a, 0x38, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0x11, 0x74, 0x02, 0x12, 
-0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb6, 0xe0, 
-0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 
-0x26, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 
-0x60, 0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, 
-0x26, 0xe5, 0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 
-0x38, 0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 0x38, 0x80, 0x19, 0x15, 0x4d, 
-0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x80, 0x09, 0x12, 0x1c, 
-0xb3, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x12, 0x1c, 0x11, 0x12, 0x19, 0xf2, 0x60, 0x05, 0x74, 
-0x01, 0x12, 0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 
-0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x14, 0x60, 0x2d, 
-0x14, 0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x04, 
-0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 
-0x0f, 0x26, 0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 
-0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb6, 
-0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 
-0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 
-0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, 
-0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 
-0x07, 0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 
-0x54, 0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60, 
-0x20, 0x24, 0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 
-0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 
-0x1d, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x0e, 
-0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0x32, 0x15, 0x4d, 
-0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1c, 
-0xb3, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 
-0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 
-0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 
-0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 
-0x60, 0x03, 0x02, 0x0f, 0x26, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 
-0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x07, 
-0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94, 
-0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 0x70, 
-0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x12, 0x31, 0x82, 
-0x40, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 
-0xe5, 0x4d, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1d, 0x64, 0x02, 0x1d, 0x2f, 0xe5, 0x35, 0x20, 
-0xe1, 0x03, 0x02, 0x0f, 0x26, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 
-0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x1c, 0xb3, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff, 
-0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 
-0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 
-0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xbb, 
-0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe, 
-0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 
-0x3b, 0x70, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
-0xba, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02, 
-0x60, 0x03, 0x02, 0x0f, 0x26, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x30, 0x12, 0x1d, 
-0x5d, 0x7d, 0x03, 0x12, 0x0f, 0x6d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 
-0xb3, 0xe0, 0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 
-0xaf, 0x3c, 0x02, 0x0f, 0xba, 0x12, 0x1c, 0x30, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x0d, 0x12, 
-0x1d, 0x5d, 0x7d, 0x14, 0x12, 0x0f, 0x6d, 0x60, 0x10, 0x02, 0x0f, 0x26, 0x12, 0x1d, 0x5d, 0x7d, 
-0x04, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 0xb3, 0xe0, 
-0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 
-0x02, 0x0f, 0xba, 0x12, 0x1d, 0x5d, 0x7d, 0x05, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 
-0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x12, 0x1c, 0x78, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 
-0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb2, 0xf0, 
-0xe4, 0xf5, 0x4c, 0x90, 0xfa, 0xb2, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1c, 
-0x72, 0x12, 0x0f, 0xcc, 0xff, 0xfd, 0x90, 0xfa, 0xb4, 0xe4, 0x8d, 0xf0, 0x12, 0x1a, 0x6c, 0x90, 
-0xfa, 0xb3, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x26, 0x05, 0x4c, 
-0x80, 0xd1, 0x12, 0x1c, 0x72, 0x12, 0x0f, 0xcc, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb3, 0xf0, 0xfd, 
-0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0x7a, 0xf9, 0x79, 0x6f, 0x7b, 0x01, 0x8b, 0x36, 
-0x8a, 0x37, 0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1c, 0x78, 0x12, 0x25, 
-0xd7, 0x8f, 0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0x11, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x12, 
-0x1c, 0x11, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0x4a, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 
-0x95, 0x3c, 0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f, 
-0x3a, 0x02, 0x2c, 0x07, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 
-0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 
-0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 
-0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 
-0x02, 0x0f, 0x26, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xa9, 0xe5, 
-0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 
-0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 0xe0, 0x94, 0x01, 
-0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 
-0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
-0xbb, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06, 
-0x53, 0x35, 0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 
-0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
-0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 
-0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 
-0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x7f, 0x01, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 
-0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 
-0xe0, 0x94, 0x00, 0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 
-0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 
-0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xff, 0x01, 0x12, 0x1d, 0x74, 0xef, 0x12, 0x1a, 0x38, 0x90, 
-0xfa, 0xb6, 0x12, 0x1d, 0x74, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0x4a, 0x90, 0x00, 0x02, 0xe4, 
-0x12, 0x1a, 0x4a, 0x74, 0x03, 0x12, 0x1c, 0x02, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0xa3, 0xe0, 0x85, 
-0x38, 0x82, 0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 
-0x4c, 0x09, 0x4a, 0x02, 0x09, 0x6c, 0x04, 0x09, 0x8e, 0x05, 0x09, 0xba, 0x06, 0x09, 0xd8, 0x07, 
-0x09, 0xf6, 0x08, 0x0a, 0x14, 0x09, 0x0a, 0x32, 0x0b, 0x0a, 0xe7, 0x80, 0x0d, 0x6f, 0x81, 0x0d, 
-0xa0, 0x82, 0x0b, 0x2e, 0x83, 0x0b, 0x77, 0x84, 0x0b, 0x96, 0x85, 0x0b, 0xdb, 0x86, 0x0c, 0x26, 
-0x87, 0x0c, 0xb7, 0x88, 0x0d, 0x42, 0x89, 0x0a, 0x50, 0x92, 0x0a, 0x50, 0x93, 0x0e, 0x53, 0xc0, 
-0x0e, 0x7f, 0xc1, 0x0e, 0x90, 0xc2, 0x00, 0x00, 0x0f, 0x15, 0xe5, 0x35, 0x20, 0xe7, 0x05, 0x7f, 
-0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 
-0x7f, 0x07, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 0x20, 0xe7, 
-0x05, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 
-0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 
-0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1d, 0x92, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b, 0x70, 
-0x05, 0x7f, 0x02, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50, 0x02, 
-0x80, 0x03, 0x02, 0x31, 0x6f, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 
-0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x08, 
-0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 
-0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02, 0x11, 
-0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 
-0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x16, 0x7f, 
-0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 
-0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 
-0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 
-0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 
-0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1c, 0xc9, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c, 
-0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75, 
-0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1b, 0x72, 0x12, 
-0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x05, 0x12, 0x31, 0xbd, 
-0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 
-0x72, 0x02, 0x2c, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0x18, 0x12, 0x1c, 0xc9, 0x60, 0x05, 
-0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1d, 0x92, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x30, 0xec, 0x90, 
-0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 
-0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 
-0x4c, 0x12, 0x1b, 0x72, 0x02, 0x31, 0x6f, 0x12, 0x1d, 0x9c, 0x12, 0x2a, 0x06, 0x12, 0x1c, 0x83, 
-0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x78, 0x68, 0x12, 0x1b, 
-0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a, 
-0x4a, 0x90, 0xfa, 0xb7, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6, 0x8c, 
-0x83, 0x12, 0x1c, 0x8b, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 
-0xb6, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 
-0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 
-0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 0xe0, 
-0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 0xb0, 
-0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0xb4, 0x01, 
-0x0a, 0x12, 0x1c, 0x11, 0xe5, 0x90, 0x12, 0x1a, 0x38, 0x80, 0x08, 0x12, 0x1c, 0x11, 0xe5, 0xb0, 
-0x12, 0x1a, 0x38, 0x02, 0x0f, 0xa9, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0x12, 0x12, 0x1c, 0x41, 
-0x20, 0xe1, 0x33, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, 
-0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1d, 0xa6, 
-0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, 
-0x80, 0x04, 0x12, 0x1d, 0xad, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 
-0x24, 0x12, 0x12, 0x1c, 0x41, 0x20, 0xe1, 0x39, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x1b, 
-0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 
-0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 
-0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 
-0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x12, 0x1c, 0xc1, 0x60, 0x4d, 0x04, 0x60, 
-0x03, 0x02, 0x0c, 0xb2, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c, 0x3a, 
-0x30, 0xe1, 0x6f, 0x12, 0x1d, 0x7c, 0x02, 0x0c, 0xb2, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb, 0x12, 
-0x1c, 0x3d, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1d, 0x7c, 0x80, 
-0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1d, 0x7c, 
-0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 
-0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0x3a, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 
-0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0x3d, 0x30, 0xe1, 0x13, 0x30, 
-0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 
-0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 
-0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0, 0x44, 
-0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 
-0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0, 0x44, 
-0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 
-0x80, 0x3b, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0, 0xa3, 
-0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3, 0xef, 
-0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0, 0xc2, 
-0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, 
-0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70, 0x16, 
-0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x80, 0x0a, 0x90, 0xff, 0xb6, 0xe0, 
-0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0x07, 0xe4, 
-0xff, 0x12, 0x30, 0xec, 0x12, 0x1d, 0x37, 0x7f, 0x03, 0x12, 0x12, 0x19, 0x90, 0xf9, 0x15, 0xe0, 
-0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80, 0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54, 
-0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30, 0x16, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 
-0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbc, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 
-0xb4, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 
-0xb9, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 
-0xb9, 0xf0, 0x12, 0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x73, 0x12, 0x1c, 0x4a, 0x90, 0xfa, 
-0xbc, 0x12, 0x1d, 0x56, 0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 
-0xfa, 0xb9, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x12, 
-0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46, 0x12, 0x1c, 0x4a, 0x80, 0xd1, 0x75, 0x4c, 0x02, 
-0x90, 0xfa, 0xbc, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb4, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 
-0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90, 0xfa, 0xbd, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c, 
-0x00, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4, 
-0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31, 
-0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x64, 0xf0, 
-0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb7, 0xe0, 0x54, 0x0f, 0x90, 
-0xf9, 0x63, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 
-0x1d, 0x9c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x30, 0xec, 
-0x12, 0x1c, 0xd0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 
-0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, 0x12, 0x1d, 0xa6, 0x12, 0x0f, 0x78, 
-0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x78, 0xff, 
-0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, 0x1d, 0xa6, 0xf0, 0x90, 0xfa, 0xb7, 
-0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 
-0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1d, 0xad, 
-0x12, 0x0f, 0x98, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 
-0x0f, 0x98, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, 0xd2, 0x92, 0x12, 0x1d, 0xad, 0xf0, 
-0xe4, 0xff, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 
-0x18, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x31, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 
-0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 
-0xfa, 0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 
-0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa, 0xb4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 
-0xb9, 0xe0, 0xf5, 0x4a, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x22, 0xa0, 
-0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, 
-0xa6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x12, 0x25, 0xd7, 0x8f, 0x4c, 0x7e, 0x00, 
-0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, 
-0xb6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 
-0x2c, 0x07, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x02, 0x31, 0x82, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c, 
-0x07, 0x12, 0x22, 0xa0, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x25, 
-0xd7, 0x90, 0xfa, 0xb1, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 
-0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 
-0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 
-0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24, 
-0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, 0x10, 0x78, 0x7f, 0x00, 0x7e, 0x00, 
-0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 
-0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 
-0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 
-0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 
-0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x12, 0x11, 0x0f, 0xd0, 0x05, 0xd0, 
-0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70, 
-0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x66, 
-0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10, 
-0x78, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 
-0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 
-0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 
-0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 
-0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 
-0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 
-0xee, 0x12, 0x11, 0x0f, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 
-0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24, 
-0xe8, 0x50, 0x05, 0x12, 0x11, 0x66, 0x80, 0xf4, 0xef, 0x60, 0x31, 0x90, 0x30, 0x54, 0xe4, 0x93, 
-0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x10, 0x78, 0xd0, 0x04, 0x43, 0x07, 0x80, 
-0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1b, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 
-0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x43, 0x12, 0x11, 0x0f, 0xd0, 0x83, 0xd0, 0x82, 
-0xd0, 0xf0, 0x22, 0x02, 0x11, 0x94, 0xc0, 0x04, 0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 
-0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 
-0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 
-0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 
-0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 
-0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 
-0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0xd2, 0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 
-0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 
-0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 
-0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc, 
-0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 
-0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f, 0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0, 
-0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6, 
-0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0x66, 0x80, 
-0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, 
-0x12, 0x11, 0x66, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
-0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 
-0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, 
-0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x36, 0xf5, 0x82, 
-0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 
-0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24, 0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, 
-0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43, 
-0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76, 0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, 
-0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x30, 0x54, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 
-0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f, 0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, 
-0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 
-0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 
-0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6, 0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, 
-0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x12, 0x41, 0xad, 0x07, 0xaf, 0x02, 
-0x12, 0x12, 0x58, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x11, 0x66, 0x80, 0xc1, 0x8f, 
-0x24, 0x12, 0x2a, 0x06, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 
-0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xed, 0xf0, 
-0x12, 0x22, 0x56, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x12, 0x22, 0x99, 0x24, 0x09, 0x12, 
-0x21, 0xf3, 0xef, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0x09, 0xc0, 
-0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 
-0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x80, 0x12, 0x22, 0x09, 
-0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x21, 
-0xf3, 0xef, 0xf0, 0xed, 0x12, 0x22, 0x99, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xed, 0xf0, 0x12, 0x21, 
-0xfb, 0xe0, 0xff, 0x30, 0xe7, 0x19, 0x12, 0x22, 0x6e, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x09, 0x12, 
-0x21, 0xfb, 0xef, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x12, 0x21, 0xfb, 0xef, 0x54, 0xfd, 0xf0, 0x78, 
-0x7e, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 
-0xfd, 0x12, 0x22, 0x43, 0xa3, 0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 
-0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x31, 0x94, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x78, 0x80, 
-0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x06, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x03, 0x43, 0x07, 
-0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x22, 0x7a, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x42, 
-0x07, 0x43, 0x07, 0x80, 0x12, 0x22, 0x8a, 0xf5, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12, 
-0x22, 0x99, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0, 
-0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, 0x03, 0x43, 0x07, 0x20, 0xec, 
-0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 
-0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x69, 0x78, 0x80, 0x12, 0x22, 0x6f, 
-0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x14, 0xa6, 0x00, 0x14, 0xda, 0x01, 0x14, 0xdf, 0x03, 
-0x14, 0xda, 0x05, 0x14, 0xdf, 0x07, 0x14, 0xda, 0x09, 0x14, 0xdf, 0x0b, 0x14, 0xda, 0x0d, 0x14, 
-0xdf, 0x0f, 0x00, 0x00, 0x14, 0xe7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x21, 0x90, 0xf9, 0x15, 0xe0, 
-0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80, 0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27, 
-0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 
-0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 
-0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x22, 0x78, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xef, 
-0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 0x54, 
-0x03, 0x70, 0x03, 0x02, 0x15, 0xd7, 0xee, 0x20, 0xe1, 0x03, 0x02, 0x15, 0xd4, 0x12, 0x22, 0x6e, 
-0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x15, 0x36, 0x00, 0x15, 0x6c, 0x01, 0x15, 0x6c, 0x03, 
-0x15, 0xa0, 0x05, 0x15, 0xa0, 0x07, 0x15, 0x86, 0x09, 0x15, 0x86, 0x0b, 0x15, 0xba, 0x0d, 0x15, 
-0xba, 0x0f, 0x00, 0x00, 0x15, 0xd7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x15, 0xe0, 
-0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53, 0x07, 0x7f, 0x02, 0x15, 0xd7, 0x43, 0x07, 0x80, 0x02, 
-0x15, 0xd7, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30, 
-0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70, 0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03, 
-0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 
-0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 
-0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37, 
-0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 
-0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 
-0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43, 
-0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x80, 0x12, 0x22, 0x3f, 0xe0, 0xfc, 0xa3, 0xe0, 
-0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05, 
-0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80, 
-0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7, 
-0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05, 
-0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80, 
-0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0x3f, 0xa3, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0x7f, 
-0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74, 
-0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 
-0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x12, 0x18, 0xe2, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2, 
-0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa, 0xcc, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 
-0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 
-0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe5, 
-0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23, 0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64, 
-0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12, 0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5, 
-0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02, 0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16, 
-0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 
-0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4, 0x41, 0x12, 0x90, 0xf9, 0x15, 0xe0, 0x44, 
-0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1, 0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x15, 
-0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60, 
-0x05, 0xe5, 0x23, 0xb4, 0x43, 0x0c, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x80, 0xf0, 0xa3, 0xe0, 0x44, 
-0x80, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x18, 0xe2, 0x90, 0xff, 
-0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1d, 0x84, 
-0x12, 0x1c, 0x30, 0x12, 0x1d, 0x8b, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x43, 0x90, 0xf9, 0x6c, 0x12, 
-0x1b, 0x43, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, 
+0xc0, 0x06, 0xc0, 0x07, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x60, 0x23, 0x74,
+0x66, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, 0xf0, 0x70, 0x16, 0x74, 0xff, 0xf0, 0x74,
+0x1c, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x60, 0x04, 0x14, 0xf0, 0x70, 0x04, 0xc2, 0x90,
+0x80, 0xfc, 0x90, 0xff, 0x93, 0x74, 0x81, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, 0x02, 0x11,
+0xdc, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xb2, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 0x83, 0xe0,
+0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, 0x90, 0xff,
+0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 0xb4, 0x02,
+0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x28, 0x4e, 0x80,
+0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 0xa3, 0xe0,
+0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, 0x90, 0xff,
+0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25, 0xb4, 0x02,
+0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x28, 0x4e, 0x80,
+0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x80, 0x03,
+0x02, 0x02, 0x90, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04, 0xf1, 0x20,
+0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x19, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, 0xfc,
+0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 0x7e, 0x01,
+0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x61, 0x12, 0x00, 0xc9, 0xee, 0x64, 0x04,
+0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 0x02, 0x60,
+0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x61, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 0x61, 0x7c,
+0x0a, 0x74, 0x19, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 0xee,
+0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 0x80, 0x10,
+0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 0xd2, 0xb1,
+0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 0x60, 0x08,
+0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d, 0x60, 0x13,
+0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x57, 0xd2,
+0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0,
+0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x90, 0xff,
+0x04, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff,
+0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 0x01, 0x7f,
+0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff, 0xea,
+0x90, 0xfa, 0xbd, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0xe0, 0xe4, 0xf5, 0x4d, 0xe5, 0x4d, 0xc3,
+0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0xc1, 0xe4, 0x12, 0x1a, 0xe8, 0x05, 0x4d, 0x04, 0x12, 0x1c,
+0xb2, 0x80, 0xea, 0x12, 0x1c, 0xe0, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 0xc0, 0x70,
+0x03, 0x02, 0x08, 0xf3, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xfe,
+0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x90, 0xff,
+0x01, 0xe0, 0x12, 0x1b, 0xfc, 0x03, 0x84, 0x00, 0x04, 0x57, 0x01, 0x05, 0x6a, 0x03, 0x06, 0x31,
+0x05, 0x06, 0x73, 0x06, 0x07, 0xd5, 0x08, 0x08, 0x1d, 0x09, 0x08, 0x79, 0x0a, 0x08, 0xb9, 0x0b,
+0x00, 0x00, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0,
+0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x64, 0x02, 0x45, 0x3b, 0x60,
+0x03, 0x02, 0x0f, 0x6e, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 0x02, 0x60,
+0x03, 0x02, 0x0f, 0x6e, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1c, 0xc1, 0x74, 0x01, 0x12,
+0x1a, 0xe8, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0xc1, 0x74, 0x02, 0x12, 0x1a, 0xe8,
+0x7f, 0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x7f,
+0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x60, 0x07,
+0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0xfa, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe5,
+0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0xbe, 0x12, 0x1a, 0xe8, 0x80,
+0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0xbe, 0x12, 0x1a, 0xe8, 0x80, 0x19, 0x15, 0x4d, 0x30, 0x0a,
+0x0b, 0x12, 0x1d, 0x55, 0x12, 0x1c, 0xbc, 0x12, 0x1a, 0xe8, 0x80, 0x09, 0x12, 0x1d, 0x63, 0x12,
+0x1c, 0xbc, 0x12, 0x1a, 0xe8, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xa2, 0x60, 0x05, 0x74, 0x01, 0x12,
+0x1a, 0xe8, 0x7f, 0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5,
+0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x14, 0x60, 0x2d, 0x14, 0x60,
+0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x04, 0xa3, 0xe0,
+0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e,
+0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x06,
+0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb9, 0xe0, 0x60,
+0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb9, 0xe0, 0xd3, 0x94, 0x01,
+0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02,
+0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0xfa, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe5,
+0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x07, 0xe5,
+0x4d, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7,
+0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60, 0x20, 0x24,
+0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f,
+0x03, 0x12, 0x2e, 0x79, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2e, 0x79, 0x80, 0x1d, 0x30,
+0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2e, 0x79, 0x80, 0x0e, 0xe4, 0xfd,
+0x7f, 0x04, 0x12, 0x2e, 0x79, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0xef, 0x15, 0x4d, 0x30, 0x0a,
+0x0b, 0x12, 0x1d, 0x55, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1d, 0x63, 0xf5,
+0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02,
+0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x14, 0x60,
+0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70,
+0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35,
+0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x07, 0xe5, 0x4d,
+0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94, 0x01, 0x40,
+0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3,
+0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x12, 0x32, 0x3f, 0x40, 0x03,
+0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x4d,
+0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1e, 0x14, 0x02, 0x1d, 0xdf, 0xe5, 0x35, 0x20, 0xe1, 0x03,
+0x02, 0x0f, 0x6e, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1d, 0x55, 0xf5, 0x83, 0xe0, 0x44, 0x08,
+0xf0, 0x80, 0x09, 0x12, 0x1d, 0x63, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff, 0x02, 0x32,
+0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02,
+0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbe, 0xe0, 0x90,
+0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe, 0xe4, 0xff,
+0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x70,
+0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0,
+0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1c, 0xe0, 0x12, 0x1e, 0x0d, 0x7d,
+0x03, 0x12, 0x0f, 0xb5, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0x72, 0x90, 0xfa, 0xb6, 0xe0,
+0xfd, 0xa3, 0x12, 0x1d, 0x2b, 0x12, 0x0f, 0xd1, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c,
+0x02, 0x10, 0x02, 0x12, 0x1c, 0xe0, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe4, 0x0d, 0x12, 0x1e, 0x0d,
+0x7d, 0x14, 0x12, 0x0f, 0xb5, 0x60, 0x10, 0x02, 0x0f, 0x6e, 0x12, 0x1e, 0x0d, 0x7d, 0x04, 0x12,
+0x10, 0x09, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0x72, 0x90, 0xfa, 0xb6, 0xe0, 0xfd, 0xa3,
+0x12, 0x1d, 0x2b, 0x12, 0x0f, 0xd1, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x02, 0x10,
+0x02, 0x12, 0x1e, 0x0d, 0x7d, 0x05, 0x12, 0x10, 0x09, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x7b, 0x01,
+0x7a, 0xfa, 0x79, 0xb6, 0x12, 0x1d, 0x28, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb7, 0xe4,
+0x75, 0xf0, 0x03, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xbe, 0xe0, 0x90, 0xfa, 0xb5, 0xf0, 0xe4, 0xf5,
+0x4c, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1d, 0x22, 0x12,
+0x10, 0x14, 0xff, 0xfd, 0x90, 0xfa, 0xb7, 0xe4, 0x8d, 0xf0, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xb6,
+0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x6e, 0x05, 0x4c, 0x80, 0xd1,
+0x12, 0x1d, 0x22, 0x12, 0x10, 0x14, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb6, 0xf0, 0xfd, 0xa3, 0xe4,
+0x75, 0xf0, 0x02, 0x12, 0x1b, 0x1c, 0x7a, 0xf9, 0x79, 0x72, 0x7b, 0x01, 0x8b, 0x36, 0x8a, 0x37,
+0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1d, 0x28, 0x12, 0x26, 0x98, 0x8f,
+0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0xc1, 0xe5, 0x4c, 0x12, 0x1a, 0xe8, 0x12, 0x1c, 0xc1,
+0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0xfa, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x3c,
+0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f, 0x3a, 0x02,
+0x2c, 0xd8, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x64,
+0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f,
+0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d,
+0x79, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f,
+0x6e, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xf1, 0xe5, 0x35, 0x30,
+0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa,
+0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xd3, 0x90, 0xfa, 0xbe, 0xe0, 0x94, 0x01, 0x90, 0xfa,
+0xbd, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03, 0x02, 0x0f,
+0x6e, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbe, 0xe0,
+0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06, 0x53, 0x35,
+0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f,
+0x6e, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0,
+0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02,
+0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1,
+0x03, 0x02, 0x0f, 0x6e, 0x7f, 0x01, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f,
+0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xd3, 0x90, 0xfa, 0xbe, 0xe0, 0x94,
+0x00, 0x90, 0xfa, 0xbd, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x64,
+0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff,
+0x02, 0x32, 0x6e, 0x90, 0xff, 0x01, 0x12, 0x1e, 0x24, 0xef, 0x12, 0x1a, 0xe8, 0x90, 0xfa, 0xb9,
+0x12, 0x1e, 0x24, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0xfa, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a,
+0xfa, 0x74, 0x03, 0x12, 0x1c, 0xb2, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0xa3, 0xe0, 0x85, 0x38, 0x82,
+0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0xfc, 0x09,
+0x7b, 0x02, 0x09, 0x9d, 0x04, 0x09, 0xbf, 0x05, 0x09, 0xeb, 0x06, 0x0a, 0x09, 0x07, 0x0a, 0x27,
+0x08, 0x0a, 0x45, 0x09, 0x0a, 0x63, 0x0b, 0x0b, 0x18, 0x80, 0x0d, 0xb7, 0x81, 0x0d, 0xe8, 0x82,
+0x0b, 0x5f, 0x83, 0x0b, 0xa8, 0x84, 0x0b, 0xc7, 0x85, 0x0c, 0x0c, 0x86, 0x0c, 0x57, 0x87, 0x0c,
+0xe8, 0x88, 0x0d, 0x73, 0x89, 0x0a, 0x81, 0x92, 0x0a, 0x81, 0x93, 0x0d, 0xa0, 0xb0, 0x0e, 0x9b,
+0xc0, 0x0e, 0xc7, 0xc1, 0x0e, 0xd8, 0xc2, 0x00, 0x00, 0x0f, 0x5d, 0xe5, 0x35, 0x20, 0xe7, 0x05,
+0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c,
+0x00, 0x7f, 0x07, 0x02, 0x11, 0x5e, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0xb4, 0xe5, 0x35, 0x20,
+0xe7, 0x05, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef,
+0xfd, 0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x5e, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0xb4, 0xe5,
+0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1e, 0x42, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b,
+0x70, 0x05, 0x7f, 0x02, 0x02, 0x31, 0xa9, 0x90, 0xfa, 0xb9, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50,
+0x02, 0x80, 0x03, 0x02, 0x32, 0x2c, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03,
+0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f,
+0x08, 0x02, 0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f,
+0x71, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02,
+0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12,
+0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x5e,
+0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71,
+0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x5e, 0x7f, 0x07,
+0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71, 0x60, 0x03,
+0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31,
+0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1d, 0x79, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5,
+0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05,
+0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1c, 0x22,
+0x12, 0x1e, 0x3b, 0x12, 0x25, 0xfa, 0x12, 0x1d, 0x89, 0x12, 0x1a, 0xbb, 0x60, 0x05, 0x12, 0x32,
+0x7a, 0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75,
+0x38, 0x75, 0x02, 0x2c, 0xd8, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0xb4, 0x12, 0x1d, 0x79, 0x60,
+0x05, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1e, 0x42, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x31, 0xa9,
+0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12,
+0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04,
+0xf5, 0x4c, 0x12, 0x1c, 0x22, 0x02, 0x32, 0x2c, 0x12, 0x1e, 0x4c, 0x12, 0x2a, 0xc7, 0x12, 0x1d,
+0x33, 0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xba, 0xf0, 0x78, 0x68, 0x12,
+0x1b, 0xd8, 0x90, 0x00, 0x02, 0x12, 0x1a, 0xbb, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12,
+0x1a, 0xfa, 0x90, 0xfa, 0xba, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6,
+0x8c, 0x83, 0x12, 0x1d, 0x3b, 0xef, 0xf0, 0x12, 0x32, 0x84, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x90,
+0xfa, 0xb9, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06,
+0xa3, 0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbe, 0xe0,
+0x42, 0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3,
+0xe0, 0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbe, 0xe0, 0x42,
+0xb0, 0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1c, 0xe0, 0x90, 0xfa, 0xb9, 0xe0, 0xb4,
+0x01, 0x0a, 0x12, 0x1c, 0xc1, 0xe5, 0x90, 0x12, 0x1a, 0xe8, 0x80, 0x08, 0x12, 0x1c, 0xc1, 0xe5,
+0xb0, 0x12, 0x1a, 0xe8, 0x02, 0x0f, 0xf1, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x24, 0x13, 0x12, 0x1c,
+0xf1, 0x20, 0xe1, 0x33, 0x12, 0x1d, 0x80, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90,
+0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1e,
+0x56, 0xf0, 0x80, 0x13, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10,
+0xf0, 0x80, 0x04, 0x12, 0x1e, 0x5d, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x90, 0xfa, 0xb9, 0xe0,
+0xff, 0x24, 0x13, 0x12, 0x1c, 0xf1, 0x20, 0xe1, 0x39, 0x12, 0x1d, 0x80, 0xef, 0x24, 0xfc, 0x60,
+0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20,
+0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xba, 0xe0,
+0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54,
+0xdf, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x12, 0x1d, 0x71, 0x60, 0x4d, 0x04,
+0x60, 0x03, 0x02, 0x0c, 0xe3, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c,
+0xea, 0x30, 0xe1, 0x6f, 0x12, 0x1e, 0x2c, 0x02, 0x0c, 0xe3, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb,
+0x12, 0x1c, 0xed, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1e, 0x2c,
+0x80, 0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1e,
+0x2c, 0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xba, 0xe0,
+0x60, 0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0xea, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44,
+0x02, 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0xed, 0x30, 0xe1, 0x13,
+0x30, 0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0,
+0x54, 0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x90, 0xfa, 0xb9, 0xe0, 0x24,
+0xfc, 0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0,
+0x44, 0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0,
+0x90, 0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0,
+0x44, 0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf,
+0xf0, 0x80, 0x3b, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0,
+0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3,
+0xef, 0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0,
+0xc2, 0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff,
+0x02, 0x31, 0xa9, 0x12, 0x1c, 0xe0, 0x90, 0xfa, 0xb9, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70,
+0x16, 0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x80, 0x0a, 0x90, 0xff, 0xb6,
+0xe0, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0xd8,
+0x90, 0xf9, 0x15, 0x74, 0x01, 0xf0, 0x90, 0xf9, 0x1c, 0x74, 0x19, 0xf0, 0x90, 0xf9, 0x66, 0x74,
+0xff, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0xe4, 0xff, 0x12, 0x31, 0xa9, 0x12, 0x1d, 0xe7, 0x7f,
+0x03, 0x12, 0x12, 0x61, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80,
+0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30,
+0xd3, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbf,
+0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 0xb7, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54,
+0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 0xbc, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e,
+0x40, 0x08, 0x90, 0xfa, 0xc0, 0xe0, 0x90, 0xfa, 0xbc, 0xf0, 0x12, 0x0f, 0x98, 0xe5, 0x31, 0x45,
+0x30, 0x70, 0x73, 0x12, 0x1c, 0xfa, 0x90, 0xfa, 0xbf, 0x12, 0x1e, 0x06, 0x60, 0x27, 0xd3, 0xef,
+0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 0xfa, 0xbc, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90,
+0xfa, 0xc0, 0xe0, 0x90, 0xfa, 0xbc, 0xf0, 0x12, 0x0f, 0x98, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46,
+0x12, 0x1c, 0xfa, 0x80, 0xd1, 0x75, 0x4c, 0x02, 0x90, 0xfa, 0xbf, 0xe4, 0xf0, 0xa3, 0x04, 0xf0,
+0x90, 0xfa, 0xb7, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90,
+0xfa, 0xc0, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c, 0x00, 0x12, 0x29, 0x60, 0x75, 0x30, 0x00, 0x8f,
+0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4, 0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26,
+0x98, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x30, 0xe7,
+0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x67, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80,
+0x11, 0x90, 0xfa, 0xba, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x65, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02,
+0xc2, 0x94, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1e, 0x4c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80,
+0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x54, 0x03, 0x14, 0x60, 0x0a,
+0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91,
+0x80, 0x23, 0x12, 0x1e, 0x56, 0x12, 0x0f, 0xc0, 0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff,
+0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0xc0, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2,
+0x91, 0x12, 0x1e, 0x56, 0xf0, 0x90, 0xfa, 0xba, 0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f,
+0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80,
+0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1e, 0x5d, 0x12, 0x0f, 0xe0, 0x60, 0x04, 0xd2, 0x92, 0x80,
+0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0xe0, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92,
+0x80, 0x02, 0xd2, 0x92, 0x12, 0x1e, 0x5d, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30,
+0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0xb4, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x32,
+0x7a, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb6, 0x90, 0xfa, 0xb7, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0,
+0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb7, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1b,
+0x1c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa,
+0xb7, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xbc, 0xe0, 0xf5, 0x4a, 0x12, 0x29, 0x60, 0x75,
+0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x23, 0x61, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22,
+0xf0, 0x7f, 0x01, 0x12, 0x12, 0x61, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xbb, 0xf0, 0x54, 0xa0,
+0x22, 0x12, 0x26, 0x98, 0x8f, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22,
+0xf0, 0x7f, 0x01, 0x12, 0x12, 0x61, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xbb, 0xf0, 0x54, 0xa0,
+0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0xd8, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x02,
+0x32, 0x3f, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c, 0xd8, 0x12, 0x23, 0x61, 0x7e, 0x00, 0x8e, 0x30,
+0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb4, 0xe0, 0x22, 0xef, 0x90,
+0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd,
+0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70,
+0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0,
+0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c,
+0xff, 0x12, 0x10, 0xc0, 0x7f, 0x00, 0x7e, 0x00, 0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1d,
+0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff,
+0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82,
+0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83,
+0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3,
+0x80, 0xda, 0x12, 0x11, 0x57, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22,
+0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70, 0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e,
+0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0xae, 0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02,
+0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10, 0xc0, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9,
+0x1d, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43,
+0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80,
+0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3,
+0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78,
+0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77,
+0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 0xee, 0x12, 0x11, 0x57, 0xd0, 0x06, 0xd0, 0x04,
+0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0,
+0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24, 0xe8, 0x50, 0x05, 0x12, 0x11, 0xae, 0x80, 0xf4,
+0xef, 0x60, 0x31, 0x90, 0x31, 0x11, 0xe4, 0x93, 0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff,
+0x12, 0x10, 0xc0, 0xd0, 0x04, 0x43, 0x07, 0x80, 0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1d,
+0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05,
+0x43, 0x12, 0x11, 0x57, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x02, 0x11, 0xdc, 0xc0, 0x04,
+0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75,
+0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04,
+0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90,
+0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90,
+0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10,
+0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0xd2,
+0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10,
+0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04,
+0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f,
+0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f,
+0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f,
+0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0, 0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8,
+0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6, 0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7,
+0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0xae, 0x80, 0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08,
+0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, 0x12, 0x11, 0xae, 0x80, 0xee, 0xd0, 0x00, 0x22,
+0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8,
+0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83,
+0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, 0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f,
+0x75, 0xf0, 0x02, 0xa4, 0x24, 0xf3, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93,
+0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24,
+0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, 0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82,
+0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43, 0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76,
+0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, 0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x31, 0x11, 0xe4,
+0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f,
+0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, 0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75,
+0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1d,
+0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6,
+0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, 0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0,
+0x07, 0x12, 0x12, 0x89, 0xad, 0x07, 0xaf, 0x02, 0x12, 0x12, 0xa0, 0xd0, 0x07, 0xa3, 0xa3, 0xa3,
+0xdf, 0xce, 0x12, 0x11, 0xae, 0x80, 0xc1, 0x8f, 0x24, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xb5, 0xa3,
+0xa3, 0xe0, 0xa3, 0x30, 0xe7, 0x28, 0x78, 0x7e, 0x12, 0x22, 0x99, 0xe0, 0x44, 0x01, 0xf0, 0x12,
+0x22, 0xfa, 0x12, 0x22, 0x9d, 0xe0, 0x20, 0xe0, 0xf6, 0x12, 0x23, 0x50, 0x74, 0x02, 0xf0, 0x12,
+0x22, 0xda, 0xe0, 0xa3, 0x30, 0xe5, 0x07, 0x12, 0x23, 0x50, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x80,
+0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0x12, 0x23,
+0x39, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x22, 0xa1, 0xed, 0xf0, 0x12, 0x23, 0x06, 0x24, 0x07, 0x12,
+0x22, 0xa1, 0xe0, 0xff, 0x12, 0x23, 0x5a, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0x90, 0xf9,
+0x16, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0xb7, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25,
+0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0,
+0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x22, 0xb5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12,
+0x23, 0x39, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0xed, 0x12, 0x23, 0x5a, 0x24,
+0x07, 0x12, 0x22, 0xa1, 0xed, 0xf0, 0x12, 0x22, 0xa9, 0xe0, 0x30, 0xe6, 0x0a, 0x12, 0x23, 0x41,
+0x24, 0x09, 0x12, 0x22, 0xa1, 0xe4, 0xf0, 0x12, 0x22, 0xa9, 0xe0, 0xff, 0x30, 0xe7, 0x1b, 0x12,
+0x23, 0x1e, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x60, 0x09, 0x12, 0x22, 0xa9, 0xef, 0x44, 0x02,
+0xf0, 0x80, 0x07, 0x12, 0x22, 0xa9, 0xef, 0x54, 0xfd, 0xf0, 0x78, 0x7e, 0x12, 0x22, 0xb7, 0xa3,
+0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x12, 0x22, 0xe0, 0xa3,
+0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0x12, 0x22, 0xa1, 0xe0,
+0x90, 0x32, 0x51, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x12, 0x23, 0x1e, 0x24, 0x06, 0x12, 0x22,
+0xa1, 0xe0, 0x60, 0x03, 0x43, 0x07, 0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x23, 0x29, 0x24,
+0x04, 0x12, 0x22, 0xa1, 0xe0, 0x42, 0x07, 0x43, 0x07, 0x80, 0x12, 0x23, 0x39, 0xf5, 0x82, 0x8a,
+0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x5a, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0xff, 0x8d,
+0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf,
+0x80, 0x03, 0x43, 0x07, 0x20, 0xec, 0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07,
+0x10, 0x12, 0x22, 0xa9, 0xe0, 0xfe, 0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1,
+0x69, 0x12, 0x23, 0x1e, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x12, 0x1b, 0xfc, 0x15, 0x2c, 0x00,
+0x15, 0x60, 0x01, 0x15, 0x65, 0x03, 0x15, 0x60, 0x05, 0x15, 0x65, 0x07, 0x15, 0x60, 0x09, 0x15,
+0x65, 0x0b, 0x15, 0x60, 0x0d, 0x15, 0x65, 0x0f, 0x00, 0x00, 0x15, 0x6d, 0xe5, 0x24, 0x64, 0x03,
+0x70, 0x21, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80,
+0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27, 0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07,
+0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d,
+0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x23, 0x27,
+0x24, 0x04, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff,
+0x12, 0x22, 0xa9, 0xe0, 0xfe, 0x54, 0x03, 0x70, 0x03, 0x02, 0x16, 0x60, 0xee, 0x20, 0xe1, 0x03,
+0x02, 0x16, 0x5d, 0x08, 0x12, 0x23, 0x20, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x12, 0x1b, 0xfc,
+0x15, 0xbf, 0x00, 0x15, 0xf5, 0x01, 0x15, 0xf5, 0x03, 0x16, 0x29, 0x05, 0x16, 0x29, 0x07, 0x16,
+0x0f, 0x09, 0x16, 0x0f, 0x0b, 0x16, 0x43, 0x0d, 0x16, 0x43, 0x0f, 0x00, 0x00, 0x16, 0x60, 0xe5,
+0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53,
+0x07, 0x7f, 0x02, 0x16, 0x60, 0x43, 0x07, 0x80, 0x02, 0x16, 0x60, 0x30, 0x94, 0x05, 0x53, 0x07,
+0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30, 0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70,
+0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef,
+0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5,
+0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e,
+0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff,
+0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07,
+0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80,
+0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f,
+0x12, 0x22, 0xda, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03,
+0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05, 0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec,
+0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80, 0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43,
+0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7, 0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03,
+0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05, 0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed,
+0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0xdc,
+0xa3, 0xef, 0xf0, 0x12, 0x32, 0x84, 0x7f, 0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3,
+0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcf, 0xe4,
+0xfd, 0x12, 0x23, 0x61, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1b, 0x1c, 0x12, 0x19,
+0x92, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2, 0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa,
+0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xcf,
+0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5,
+0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0xe5, 0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23,
+0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64, 0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12,
+0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5, 0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02,
+0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16, 0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90,
+0xf9, 0x16, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4,
+0x41, 0x12, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1,
+0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x44,
+0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60, 0x0c, 0xe5, 0x23, 0x64, 0x43, 0x60, 0x06, 0xe5, 0x23,
+0x64, 0x44, 0x70, 0x2e, 0x90, 0xf9, 0x16, 0xe0, 0xff, 0xe5, 0x23, 0xb4, 0x44, 0x04, 0x7e, 0x40,
+0x80, 0x02, 0x7e, 0x00, 0xee, 0x24, 0x80, 0x4f, 0x90, 0xf9, 0x16, 0xf0, 0xa3, 0xe0, 0xff, 0xe5,
+0x23, 0xb4, 0x44, 0x04, 0x7e, 0x40, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x24, 0x80, 0x4f, 0x90, 0xf9,
+0x17, 0xf0, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x19, 0x92, 0x90, 0xff,
+0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1e, 0x34,
+0x12, 0x1c, 0xe0, 0x12, 0x1e, 0x3b, 0x90, 0xf9, 0x6a, 0x12, 0x1b, 0xf3, 0x90, 0xf9, 0x6f, 0x12,
+0x1b, 0xf3, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81,
 0x74, 0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x23, 0xe5, 0x23, 
-0x12, 0x1c, 0xa7, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1c, 0xb5, 0xf5, 0x83, 0xe4, 0xf0, 
-0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x31, 
-0x4d, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x31, 0x5a, 0xe4, 0x93, 0xff, 
-0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1c, 0x97, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, 
+0x12, 0x1d, 0x57, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1d, 0x65, 0xf5, 0x83, 0xe4, 0xf0,
+0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x32,
+0x0a, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x32, 0x17, 0xe4, 0x93, 0xff,
+0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1d, 0x47, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0,
 0x08, 0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, 
-0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0x28, 0xce, 0xc3, 0x13, 0xce, 
-0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1c, 0xf8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0x1e, 0xe4, 0xf5, 
-0x23, 0xe5, 0x23, 0x90, 0x31, 0x47, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0, 
-0x24, 0x4e, 0xf5, 0x82, 0xe4, 0x34, 0x31, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, 
-0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0x97, 0x12, 0x1d, 0x06, 0x24, 0x47, 0xf5, 0x82, 
-0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, 
-0x1c, 0xf8, 0xef, 0xf0, 0x12, 0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 
-0x0b, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0x1e, 
+0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0xd8, 0xce, 0xc3, 0x13, 0xce,
+0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1d, 0xa8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0xce, 0xe4, 0xf5,
+0x23, 0xe5, 0x23, 0x90, 0x32, 0x04, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0,
+0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x34, 0x32, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7,
+0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1d, 0x47, 0x12, 0x1d, 0xb6, 0x24, 0x47, 0xf5, 0x82,
+0xe4, 0x34, 0xff, 0x12, 0x1c, 0xc8, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12,
+0x1d, 0xa8, 0xef, 0xf0, 0x12, 0x1c, 0xcf, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d,
+0xbb, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0xce,
 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 
-0xf0, 0x02, 0x18, 0xb7, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0xea, 0x12, 0x1d, 0x06, 
-0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 
-0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, 
-0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x05, 0xf5, 0x82, 
+0xf0, 0x02, 0x19, 0x67, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1d, 0x9a, 0x12, 0x1d, 0xb6,
+0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0xc8, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8,
+0xf9, 0x12, 0x1d, 0xbb, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12,
+0x1c, 0xcf, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0xbb, 0x24, 0x05, 0xf5, 0x82,
 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 
 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 
 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x23, 0xe5, 0x23, 0x64, 0x04, 0x60, 0x03, 0x02, 
-0x17, 0xe1, 0x90, 0x31, 0x4c, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1c, 0xe8, 0xe4, 0xf0, 
-0x90, 0x31, 0x4b, 0x93, 0xff, 0xf6, 0x12, 0x1c, 0x95, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, 
-0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 
-0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0xe7, 0x09, 0xf6, 0x08, 
+0x18, 0x91, 0x90, 0x32, 0x09, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1d, 0x98, 0xe4, 0xf0,
+0x90, 0x32, 0x08, 0x93, 0xff, 0xf6, 0x12, 0x1d, 0x45, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05,
+0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12,
+0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x26, 0x98, 0xe7, 0x09, 0xf6, 0x08,
 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, 
 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, 
 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, 
@@ -445,7 +456,7 @@ static unsigned char IMAGE_ARRAY_NAME[] =
 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, 
 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, 
 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x19, 
-0x4c, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 
+0xfc, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb,
 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, 
 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, 
 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, 
@@ -469,364 +480,365 @@ static unsigned char IMAGE_ARRAY_NAME[] =
 0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 0x83, 0xd0, 0x82, 
 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 
 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 
-0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 
+0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25,
 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0x74, 0x11, 0x12, 
-0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06, 
-0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 
-0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0x38, 0x04, 0x25, 
+0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06,
+0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38,
+0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0xe8, 0x04, 0x25,
 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 
-0x38, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab, 
-0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 
-0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 
+0xe8, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab,
+0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35,
+0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8,
 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x22, 0xf5, 0x83, 0xe0, 0x54, 
 0x08, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, 
 0x78, 0x7b, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, 
-0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x6f, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x12, 
-0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 
-0x00, 0xc3, 0x90, 0xfa, 0xbd, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbc, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 
-0xb4, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5, 
-0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb1, 0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 
+0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x72, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x13,
+0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xbc, 0xe0, 0xff, 0x7e,
+0x00, 0xc3, 0x90, 0xfa, 0xc0, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x9e, 0xf0, 0x90, 0xfa,
+0xb7, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5,
+0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb4, 0x90, 0xfa, 0xb7, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0,
 0xf5, 0x2e, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, 
 0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, 
 0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, 
 0x34, 0xff, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, 
-0x22, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, 
-0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9, 
-0x6c, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 
+0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22,
+0x90, 0xfa, 0xbe, 0xe0, 0x90, 0xfa, 0xba, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9,
+0x6f, 0x12, 0x1b, 0xea, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00,
 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, 
 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, 
-0xa4, 0x22, 0x74, 0xaf, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, 
+0xa4, 0x22, 0x74, 0xb2, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0,
 0x08, 0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, 
 0xff, 0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, 
 0xfc, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x67, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, 
-0x65, 0xf0, 0x22, 0x12, 0x1b, 0x1c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, 
-0xfa, 0x79, 0xb4, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, 
-0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x67, 0x02, 0x1b, 0x3a, 0x90, 0xff, 0xa4, 0xe0, 
+0x65, 0xf0, 0x22, 0x12, 0x1b, 0xcc, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a,
+0xfa, 0x79, 0xb7, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0,
+0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x6a, 0x02, 0x1b, 0xea, 0x90, 0xff, 0xa4, 0xe0,
 0x44, 0x02, 0xf0, 0x22, 0x75, 0x39, 0x01, 0x75, 0x3a, 0x09, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 0x79, 
-0x6f, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbb, 0xe0, 
-0xff, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, 
-0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0x06, 0x12, 0x22, 
-0x4a, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x0a, 
-0x12, 0x22, 0x52, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0x4a, 0x12, 
-0x22, 0x4a, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x22, 0x56, 0x24, 
-0x04, 0x12, 0x21, 0xf3, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55, 
+0x72, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbe, 0xe0,
+0xff, 0x90, 0xfa, 0xba, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4,
+0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x4b, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0xc7, 0x12, 0x22,
+0xfa, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x0a,
+0x12, 0x23, 0x02, 0x24, 0x0a, 0x12, 0x22, 0xa1, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0xfa, 0x12,
+0x22, 0xfa, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x23, 0x06, 0x24,
+0x04, 0x12, 0x22, 0xa1, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55,
 0xe5, 0x53, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x88, 0xf6, 0xd3, 0x94, 0x00, 0x40, 0x06, 
-0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x0c, 0xef, 
-0x12, 0x1a, 0x4a, 0x78, 0x80, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53, 
-0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20, 
-0xe5, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02, 
-0xe5, 0x53, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20, 
-0xe5, 0x53, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07, 
-0x80, 0xe5, 0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06, 
-0x08, 0xe5, 0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 
-0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0, 
-0x12, 0x1a, 0xef, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22, 
-0x2c, 0x90, 0x00, 0x08, 0xef, 0x12, 0x1a, 0x4a, 0x80, 0x0a, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x08, 
-0xe4, 0x12, 0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x07, 0xef, 0x12, 
-0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0x4a, 0x90, 
-0x00, 0x07, 0x12, 0x1a, 0x0b, 0x70, 0x13, 0x12, 0x22, 0x2d, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a, 
-0xfa, 0x12, 0x19, 0xf2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0x38, 0x12, 0x22, 0x78, 0x24, 0x08, 0x12, 
-0x21, 0xf3, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 
-0xfd, 0xee, 0xed, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0xef, 0x12, 
-0x31, 0xc7, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0x90, 0xfa, 0xe3, 0xe0, 
-0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xd7, 
-0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xff, 0x7e, 0x00, 0x90, 0xfa, 
-0xd3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1a, 
-0x98, 0xff, 0x90, 0xfa, 0xd5, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e, 
-0x50, 0x8f, 0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa, 
-0xd8, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd6, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90, 
-0xfa, 0xda, 0xf0, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0x90, 0xfa, 0xd3, 0xe0, 0x94, 0x00, 0x50, 
-0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 
-0x2d, 0x5a, 0x90, 0xfa, 0xd3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xd7, 
-0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xda, 
-0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd4, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 
-0xe0, 0xff, 0x22, 0x12, 0x2d, 0x5a, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 
-0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b, 
-0x01, 0x90, 0xfa, 0xd5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xda, 0xe0, 0xf5, 0x4a, 0x12, 
-0x28, 0x9f, 0x90, 0xfa, 0xd9, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60, 
-0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x20, 0xbb, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0x03, 0x78, 
-0x71, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33, 
-0x90, 0xfa, 0x91, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, 0x22, 0x78, 
-0x72, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43, 
-0x90, 0xfa, 0x93, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb0, 0x74, 0x01, 0xf0, 0x22, 0x90, 
-0xfa, 0x9d, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0x03, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 
-0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 
-0xa6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 
-0xcb, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x2c, 0xb4, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xcb, 0xe0, 
-0xff, 0x74, 0x34, 0x90, 0xfa, 0x95, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa7, 0xe0, 0xa3, 
-0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 
-0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xb6, 
-0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12, 
-0x2c, 0xb4, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x97, 0xf0, 
-0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 
-0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 
-0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc9, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef, 
-0x12, 0x1b, 0x4c, 0x21, 0xbb, 0x26, 0x21, 0xbb, 0x2e, 0x21, 0x5e, 0x30, 0x21, 0x5e, 0x32, 0x21, 
-0x6c, 0x38, 0x21, 0x7e, 0x3a, 0x21, 0xb0, 0x3e, 0x21, 0x9b, 0x44, 0x21, 0x90, 0x46, 0x21, 0xa6, 
-0x50, 0x21, 0xa6, 0x52, 0x21, 0xa6, 0x54, 0x21, 0xa6, 0x56, 0x00, 0x00, 0x21, 0xc0, 0x90, 0xfa, 
-0xc9, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x16, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01, 
-0x7f, 0x03, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00, 
-0x7d, 0x01, 0x7f, 0x02, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e, 
-0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x16, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 
-0x06, 0x12, 0x11, 0x16, 0x80, 0x28, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x12, 0x20, 0x18, 0x80, 0x1e, 
-0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x16, 0x80, 0x13, 0x12, 0x27, 0x8d, 0x80, 0x0e, 
-0x90, 0xfa, 0xc9, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2c, 0xb4, 0xd0, 0x07, 
-0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 
-0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24, 
-0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x12, 0x25, 0x24, 0xf5, 
-0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 
-0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 
-0xff, 0x7a, 0x31, 0x79, 0x99, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x19, 0xcc, 0xff, 0x90, 0xf9, 0x6c, 
-0x02, 0x1b, 0x3a, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x04, 0x02, 0x1a, 0x0b, 0xe6, 
-0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6, 
-0xff, 0x22, 0xed, 0x12, 0x1a, 0x4a, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, 
-0xfa, 0xcb, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x08, 0xe6, 
-0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x09, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 
-0x83, 0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6, 
-0xfb, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82, 0x22, 
-0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x02, 
-0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 
-0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xce, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3, 0xe0, 
-0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xce, 0xe0, 
-0xff, 0x90, 0xfa, 0xd1, 0xe4, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xd1, 
-0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xcf, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xce, 0xe0, 
-0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x04, 0x12, 0x1a, 
-0x6c, 0x02, 0x22, 0xb1, 0x90, 0xfa, 0xd0, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xcf, 0xe0, 0x34, 
-0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1a, 0xd0, 0x7f, 0x00, 0x22, 0x7b, 
-0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x6c, 0x85, 
-0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0x8f, 0x62, 0x12, 0x2a, 0x06, 0x12, 0x22, 
-0x4a, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0, 0x08, 
-0x12, 0x22, 0x3f, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x22, 0x56, 0x24, 0x0b, 0x12, 0x21, 0xf3, 
-0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 
-0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82, 0x24, 
-0x04, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0x74, 
-0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x21, 0xf3, 0xc0, 
-0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x96, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 
-0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 
-0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 
-0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 
-0x10, 0x03, 0x7f, 0x02, 0x12, 0x12, 0x19, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, 
-0xb1, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36, 0xd2, 
-0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7c, 
-0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x7a, 
-0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, 
-0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe4, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, 
-0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, 
-0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0, 
-0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7a, 0xe0, 
-0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe4, 0xe0, 
-0xf5, 0xa8, 0x02, 0x10, 0x86, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 
-0xc0, 0x12, 0x1b, 0x43, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x43, 0x90, 0xfa, 
-0xc4, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x3a, 0xe9, 0x24, 
-0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, 
-0x5e, 0x12, 0x2d, 0x48, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa, 0xbe, 
-0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc0, 0x12, 0x2d, 0x1d, 0xff, 
-0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0x1d, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83, 0xf6, 
-0x12, 0x2d, 0x1a, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0x23, 0x75, 0xf0, 0x02, 0x12, 
-0x1a, 0x6c, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0xab, 0x5c, 0xaa, 0x5d, 
-0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x0b, 0x30, 0xe4, 0x03, 0x12, 0x2d, 0x32, 0x78, 0x82, 
-0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbf, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58, 0x90, 
-0xfa, 0xbf, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 
-0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x24, 0x95, 
-0x80, 0x62, 0x12, 0x2d, 0x53, 0x12, 0x1f, 0x2c, 0x90, 0xfa, 0xbf, 0xef, 0xf0, 0x80, 0x55, 0x90, 
-0xfa, 0xbf, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, 
-0x12, 0x2c, 0x5f, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b, 0x01, 
-0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xfd, 
-0x90, 0x00, 0x08, 0x12, 0x1a, 0x98, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 
-0x03, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, 
-0xbf, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x02, 0x12, 0x1a, 
-0x4a, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c, 0xe5, 
-0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2d, 0x82, 0x70, 0x16, 0x12, 0x2d, 0xa1, 0xe5, 0x2d, 
-0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x26, 0x64, 0x40, 0x0b, 0x7f, 0x00, 
-0x22, 0x12, 0x2d, 0xa1, 0x12, 0x26, 0x64, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, 
-0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, 
-0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0x04, 0x40, 
-0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, 
-0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2d, 0x94, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b, 0xe4, 
-0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0x04, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2d, 
-0x94, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0x1b, 0x12, 0x10, 0x03, 
-0x78, 0x84, 0x12, 0x22, 0x82, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x30, 0xec, 0x02, 0x26, 0xfb, 
-0x78, 0x84, 0xe6, 0xf9, 0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54, 0x03, 
-0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44, 0x04, 
-0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x39, 
-0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x80, 
-0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef, 0x54, 
-0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, 
-0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x17, 0xe0, 0x04, 0xf0, 0xaf, 
-0x01, 0x12, 0x22, 0x33, 0xfd, 0x12, 0x2f, 0x49, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x75, 0xa8, 
-0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x27, 0x48, 0x02, 0x30, 0xcf, 
-0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 
-0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 
-0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 
-0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0x4c, 0xe4, 0x7e, 0x01, 0x93, 0x60, 
-0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 
-0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 
-0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 
-0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x22, 
-0x12, 0x1d, 0x12, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x2f, 0x77, 0x12, 
-0x1d, 0x12, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x22, 
-0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1d, 0x53, 0x60, 0x2c, 0x12, 0x2c, 0xb4, 
-0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 
-0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0x9d, 0x12, 0x1b, 0x1c, 0xe0, 0xa3, 0x30, 
-0xe6, 0x33, 0x12, 0x1d, 0x12, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 
-0x95, 0x12, 0x1d, 0x53, 0x60, 0x16, 0x12, 0x2c, 0xb4, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, 
-0x22, 0x90, 0xfa, 0x95, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5, 0x22, 
-0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, 
-0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, 
-0x1c, 0x11, 0x12, 0x1a, 0x38, 0x0f, 0x12, 0x1c, 0x00, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x3a, 
-0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5, 0x39, 
-0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x84, 
-0x12, 0x1d, 0x76, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, 
-0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0x0b, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, 
-0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x16, 0x12, 0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 
-0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 0x12, 0x31, 0xb1, 0x22, 0x8b, 
-0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2d, 0x82, 0x70, 0x16, 
-0x12, 0x2d, 0xa1, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x29, 
-0x14, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2d, 0xa1, 0x12, 0x29, 0x14, 0x50, 0xf8, 0xe4, 0xf5, 
-0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0x04, 0x40, 0x03, 
-0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5, 0x46, 
-0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0x04, 0x40, 0x03, 0x7f, 0x18, 
-0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x19, 0xf2, 0x90, 0xff, 0xf1, 
-0xf0, 0x02, 0x31, 0x1b, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0x1b, 0x7b, 0x01, 0x7a, 
-0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x09, 0x12, 
-0x1a, 0x6c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 
-0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xff, 0xf7, 0xe5, 
-0x23, 0x12, 0x29, 0x78, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 
-0x74, 0x06, 0x12, 0x29, 0x78, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, 
-0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 
-0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 
-0x02, 0x25, 0xd7, 0x90, 0xff, 0x93, 0x74, 0x2a, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, 
-0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9, 0x15, 
-0xf0, 0xa3, 0xf0, 0x12, 0x2a, 0x78, 0x12, 0x16, 0x42, 0x12, 0x2f, 0xcd, 0x7e, 0x07, 0x7f, 0xd0, 
-0x12, 0x11, 0xe2, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0xfc, 0xe4, 0x78, 0x77, 0xf6, 0x78, 0x77, 
-0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77, 0x06, 
-0x80, 0xec, 0x7f, 0x03, 0x12, 0x2e, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x20, 0xe4, 0x05, 0x7f, 0x04, 
-0x12, 0x2e, 0xb3, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, 0xe0, 
-0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05, 0x12, 
-0x11, 0x66, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c, 0x76, 
-0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76, 0xff, 
-0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76, 0x9b, 
-0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x22, 0x92, 0x7b, 0x01, 0x7a, 0xff, 
-0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0x31, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08, 0xa4, 
-0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x22, 0x92, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0x31, 0x78, 
-0x6d, 0xef, 0x12, 0x22, 0x92, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0, 0xe0, 
-0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 
-0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7e, 0x00, 0x90, 0xfa, 0xe1, 0xee, 0xf0, 
-0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x52, 0x09, 0x90, 0xf9, 
-0x15, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe1, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 
-0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x10, 
-0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe3, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x54, 0xef, 0xf0, 
-0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x12, 0x10, 0x03, 0x78, 0x8a, 0xef, 0xf6, 0x12, 
-0x2a, 0x06, 0x12, 0x22, 0x33, 0x30, 0xe0, 0x25, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x7f, 0xf0, 0x78, 
-0x6b, 0x12, 0x1b, 0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, 
-0xe4, 0x12, 0x1a, 0x4a, 0x80, 0xe9, 0x12, 0x22, 0x07, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x22, 0x33, 
-0x30, 0xe1, 0x1e, 0x12, 0x21, 0xe9, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x31, 0x5c, 0x78, 0x68, 0x12, 
-0x1b, 0x28, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0x4a, 0x12, 0x21, 0xe9, 0xe0, 0x44, 0x80, 
-0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x03, 0x68, 0x01, 0xff, 
-0x48, 0x03, 0x6b, 0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x95, 0x00, 0x00, 0x00, 
-0x00, 0x44, 0xfa, 0x91, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xaf, 0x00, 0x00, 0x42, 0xfa, 0x7b, 
-0x00, 0x00, 0x42, 0xfa, 0x79, 0x00, 0x00, 0x42, 0xf9, 0x6a, 0xff, 0xff, 0x42, 0xfa, 0x77, 0x00, 
-0x00, 0x43, 0xf9, 0x18, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x65, 0x20, 0x41, 0xf9, 0x66, 0x20, 0x41, 
-0xf9, 0x63, 0x00, 0x41, 0xf9, 0x64, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9, 
-0x15, 0x00, 0x00, 0x41, 0xf9, 0x17, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 
-0x10, 0x03, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x30, 0x93, 0x12, 0x30, 0xec, 0x78, 0x85, 0xe6, 0xff, 
-0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 
-0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80, 0x19, 
-0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 
-0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x14, 0xf0, 0xe0, 
-0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0x86, 0x12, 0x1d, 0x6c, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 
-0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00, 0x40, 
-0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 
-0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1d, 0x84, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12, 0x1c, 
-0x11, 0x12, 0x19, 0xf2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, 
-0xf0, 0x0e, 0x12, 0x1c, 0x00, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, 
-0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2d, 0x48, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, 
-0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xe5, 0x5b, 
-0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x43, 0xe4, 0x90, 0xfa, 
-0xbf, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f, 0x50, 
-0x12, 0x12, 0x2d, 0x1a, 0xff, 0x12, 0x2d, 0x23, 0x12, 0x2d, 0x36, 0x78, 0x8b, 0x06, 0x12, 0x2d, 
-0x32, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x31, 0x4d, 0xe4, 0x93, 0xff, 0x78, 0x74, 
-0xf6, 0x54, 0x0f, 0x12, 0x1c, 0xf8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c, 0x29, 
-0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, 
-0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, 
-0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 
-0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x90, 
-0x00, 0x03, 0x12, 0x1a, 0x0b, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x3a, 
-0x02, 0x19, 0xf2, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x3a, 0xef, 0x12, 0x1a, 0x38, 0x90, 0xfa, 0xc7, 
-0xe4, 0x22, 0x90, 0xfa, 0xc1, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1a, 0x6c, 0x90, 0x00, 0x08, 0x12, 
-0x1a, 0x98, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0x90, 0xfa, 
-0xbe, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xda, 0xe0, 0xff, 0x7e, 
-0x00, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd3, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 
-0xd5, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50, 0xf5, 
-0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe3, 
-0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02, 0x1a, 
-0x38, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64, 0xb4, 
-0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0x32, 0x7f, 0x02, 0x02, 0x31, 0x32, 0xaf, 0x64, 0x12, 0x2a, 
-0x06, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1c, 0x83, 0xe0, 
-0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12, 0x31, 
-0x32, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0x32, 0x30, 0x09, 0x07, 0x12, 0x1c, 0x83, 0xe0, 0x44, 
-0x80, 0xf0, 0x12, 0x31, 0xc7, 0x22, 0x12, 0x10, 0x03, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, 
-0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, 
-0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, 
-0xf0, 0x80, 0x0d, 0x12, 0x1d, 0x2f, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, 
-0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xb0, 0x12, 0x1d, 0x37, 0x02, 0x10, 0x86, 
-0x12, 0x10, 0x03, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0x06, 0x90, 0xf9, 0x67, 0x12, 
-0x1b, 0x3a, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe, 0x08, 
-0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0x25, 0x12, 0x31, 0xc7, 
-0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x3f, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x8f, 0x63, 0x12, 
-0x2a, 0x06, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 
-0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 
-0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 
-0x7f, 0x00, 0x22, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 0x78, 0x7e, 0x12, 
-0x21, 0xeb, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x22, 0x4a, 0x12, 0x21, 0xef, 0xe0, 0x20, 0xe0, 0xf6, 
-0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 
-0xaf, 0x23, 0x12, 0x13, 0x3f, 0x22, 0x12, 0x10, 0x03, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x4a, 0x24, 
-0x06, 0x12, 0x21, 0xf1, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x03, 0x12, 0x22, 0x52, 0x24, 
-0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x4a, 0x12, 0x31, 0xc7, 0x7d, 0x02, 
-0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0xae, 0x05, 0x12, 0x1c, 0xde, 0xef, 0x12, 0x1a, 
-0x4a, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee, 
-0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 
-0x12, 0x1a, 0x4a, 0xaf, 0x06, 0x12, 0x31, 0xb1, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 
-0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 
-0x74, 0x6e, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, 0x74, 0x96, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 
-0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 
-0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 
-0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 
-0x00, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 
-0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00, 
-0x40, 0x05, 0x12, 0x28, 0x16, 0x80, 0x03, 0x12, 0x31, 0xbd, 0x02, 0x10, 0x86, 0x90, 0xff, 0xfc, 
-0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 
-0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 
-0xf0, 0x80, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 
-0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x19, 
-0x12, 0x1d, 0x46, 0x02, 0x10, 0x86, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f, 
-0x70, 0x02, 0x15, 0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 
-0x12, 0x0f, 0xdc, 0x80, 0xe5, 0x22, 0x11, 0x94, 0x2d, 0xf6, 0x23, 0xef, 0x31, 0xa3, 0x2f, 0xf4, 
-0x2f, 0xa2, 0x30, 0xb2, 0x2e, 0xe6, 0x26, 0x6d, 0x2b, 0xaf, 0x30, 0x55, 0x30, 0x74, 0x1d, 0xb4, 
-0x2e, 0x40, 0x2a, 0xe8, 0x0e, 0x12, 0x10, 0x03, 0x78, 0x86, 0x12, 0x22, 0x82, 0x20, 0xe1, 0x07, 
-0x7f, 0x12, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x23, 0x49, 0x12, 0x30, 
-0xec, 0x02, 0x10, 0x86, 0x12, 0x10, 0x03, 0x78, 0x87, 0x12, 0x22, 0x82, 0x20, 0xe2, 0x07, 0x7f, 
-0x11, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2e, 0x7d, 0x12, 0x30, 0xec, 
-0x02, 0x10, 0x86, 0x8f, 0x61, 0x12, 0x2e, 0x7d, 0xaf, 0x61, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 
-0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13, 
-0x3f, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 
-0x05, 0x12, 0x2c, 0x07, 0x80, 0x06, 0x12, 0x1d, 0x64, 0x12, 0x1d, 0x6c, 0x02, 0x10, 0x86, 0x12, 
-0x29, 0x93, 0x12, 0x12, 0xbb, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12, 
-0x58, 0x12, 0x29, 0x1d, 0x12, 0x12, 0xf7, 0x12, 0x11, 0x74, 0x80, 0xe3, 0x12, 0x1c, 0xde, 0xef, 
-0x12, 0x1a, 0x4a, 0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 
-0x12, 0x31, 0xb1, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 
-0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 
-0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 
-0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, 0x1c, 0x95, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 
-0x1c, 0xe8, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 
-0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22, 
-0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 
-0x3b, 0x39, 0x85, 0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 
-0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x31, 0x47, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 
-0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x12, 0x10, 0x03, 0x7f, 0x02, 0x12, 0x10, 0x92, 0x12, 0x1d, 0x46, 0x02, 0x10, 
-0x86, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x12, 0x1c, 0x30, 0x12, 0x2c, 0x07, 0x22, 0x12, 0x1d, 0x6c, 
-0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x64, 0x22, 0xc2, 0x08, 0x22, 
+0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x0c, 0xef,
+0x12, 0x1a, 0xfa, 0x12, 0x22, 0xb5, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0x0c,
+0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20, 0xe5, 0x0e,
+0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02, 0xe5, 0x53,
+0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20, 0xe5, 0x53,
+0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07, 0x80, 0xe5,
+0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06, 0x08, 0xe5,
+0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43,
+0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0, 0x12, 0x1b,
+0x9f, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22, 0xe7, 0x90,
+0x00, 0x08, 0xef, 0x12, 0x1a, 0xfa, 0x80, 0x0a, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x08, 0xe4, 0x12,
+0x1a, 0xfa, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x07, 0xef, 0x12, 0x1a, 0xfa,
+0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0xfa, 0x90, 0x00, 0x07,
+0x12, 0x1a, 0xbb, 0x70, 0x13, 0x12, 0x22, 0xe8, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a, 0xfa, 0x12,
+0x1a, 0xa2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0xe8, 0x12, 0x23, 0x27, 0x24, 0x08, 0x12, 0x22, 0xa1,
+0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0xee,
+0xed, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x9f, 0x12, 0x32, 0x84,
+0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0xb4, 0x02, 0x10, 0xce, 0x90, 0xfa, 0xe6, 0xe0, 0xb4, 0x03,
+0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xda, 0xee, 0xf0,
+0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb, 0xff, 0x7e, 0x00, 0x90, 0xfa, 0xd6, 0xee,
+0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1b, 0x48, 0xff,
+0x90, 0xfa, 0xd8, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e, 0x50, 0x8f,
+0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa, 0xdb, 0xe0,
+0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd9, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90, 0xfa, 0xdd,
+0xf0, 0xc3, 0x90, 0xfa, 0xd7, 0xe0, 0x9f, 0x90, 0xfa, 0xd6, 0xe0, 0x94, 0x00, 0x50, 0x06, 0xa3,
+0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x12, 0x20, 0xa9, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 0x2e, 0x2b,
+0x90, 0xfa, 0xd6, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xda, 0xe0, 0xfc,
+0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x80,
+0x08, 0x90, 0xfa, 0xd7, 0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x12, 0x20, 0xa9, 0x60, 0x03, 0xe0, 0xff,
+0x22, 0x12, 0x2e, 0x2b, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 0x2d, 0xf5,
+0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b, 0x01, 0x90,
+0xfa, 0xd8, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xdd, 0xe0, 0xf5, 0x4a, 0x12, 0x29, 0x60,
+0x90, 0xfa, 0xdc, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60, 0x2e, 0x24,
+0xfe, 0x70, 0x03, 0x02, 0x21, 0x69, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0xb1, 0x78, 0x71, 0xe6,
+0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33, 0x90, 0xfa,
+0x94, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb2, 0x74, 0x01, 0xf0, 0x22, 0x78, 0x72, 0xe6,
+0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43, 0x90, 0xfa,
+0x96, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb3, 0x74, 0x01, 0xf0, 0x22, 0x90, 0xfa, 0xa0,
+0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0xb1, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0,
+0xa3, 0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xa6, 0x12,
+0x23, 0x0d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xce, 0xe0,
+0xff, 0x74, 0x34, 0xfe, 0x12, 0x2d, 0x85, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74,
+0x34, 0x90, 0xfa, 0x98, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xaa, 0xe0, 0xa3, 0x30, 0xe5,
+0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xff,
+0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x23, 0x0d, 0x90, 0xff, 0xb6, 0xe0, 0x90,
+0xfa, 0xcd, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12, 0x2d, 0x85,
+0xef, 0x70, 0x0e, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x9a, 0xf0, 0xef, 0xa3,
+0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0,
+0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x90,
+0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xcc, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef, 0x12, 0x1b,
+0xfc, 0x22, 0x69, 0x26, 0x22, 0x69, 0x2e, 0x22, 0x0c, 0x30, 0x22, 0x0c, 0x32, 0x22, 0x1a, 0x38,
+0x22, 0x2c, 0x3a, 0x22, 0x5e, 0x3e, 0x22, 0x49, 0x44, 0x22, 0x3e, 0x46, 0x22, 0x54, 0x50, 0x22,
+0x54, 0x52, 0x22, 0x54, 0x54, 0x22, 0x54, 0x56, 0x00, 0x00, 0x22, 0x6e, 0x90, 0xfa, 0xcc, 0xe0,
+0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x5e, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x03,
+0x12, 0x11, 0x5e, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00, 0x7d, 0x01,
+0x7f, 0x02, 0x12, 0x11, 0x5e, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e, 0x7c, 0x00,
+0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x5e, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x06, 0x12,
+0x11, 0x5e, 0x80, 0x28, 0x90, 0xfa, 0xcc, 0xe0, 0xff, 0x12, 0x20, 0xc6, 0x80, 0x1e, 0x7c, 0x00,
+0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x5e, 0x80, 0x13, 0x12, 0x28, 0x4e, 0x80, 0x0e, 0x90, 0xfa,
+0xcc, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2d, 0x85, 0xd0, 0x07, 0xd0, 0x06,
+0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82,
+0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24, 0x04, 0x8e,
+0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x13, 0x25, 0x24, 0xf5, 0x82, 0xe4,
+0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0x22,
+0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 0xff, 0x7a,
+0x32, 0x79, 0x56, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x1a, 0x7c, 0x78, 0x80, 0xe6, 0xfc, 0x08, 0xe6,
+0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0xff, 0x90, 0xf9, 0x6f, 0x02, 0x1b, 0xea, 0x90, 0xf9,
+0x6a, 0x12, 0x1b, 0xea, 0x90, 0x00, 0x04, 0x02, 0x1a, 0xbb, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6,
+0xff, 0x22, 0xed, 0x12, 0x1a, 0xfa, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90,
+0xfa, 0xce, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x78, 0x80,
+0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 0x83,
+0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6, 0xfb,
+0x22, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22,
+0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82,
+0x22, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xd2, 0xe4, 0xf0, 0xa3, 0x74,
+0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xd1, 0x90, 0xfa, 0xd2, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0,
+0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xd1, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3,
+0xe0, 0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0xf0, 0x90, 0xfa, 0xd1,
+0xe0, 0xff, 0x90, 0xfa, 0xd4, 0xe4, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0x12, 0x23, 0xf0, 0x90, 0xfa,
+0xd4, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xd2, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xd1,
+0xe0, 0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xd2, 0xe4, 0x75, 0xf0, 0x04, 0x12,
+0x1b, 0x1c, 0x02, 0x23, 0x72, 0x90, 0xfa, 0xd3, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xd2, 0xe0,
+0x34, 0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1b, 0x80, 0x7f, 0x00, 0x22,
+0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xd1, 0x90, 0xfa, 0xd2, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1b, 0x1c,
+0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x26, 0x98, 0x8f, 0x62, 0x12, 0x2a, 0xc7, 0x12,
+0x22, 0xfa, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0,
+0x08, 0x12, 0x22, 0xdc, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x23, 0x06, 0x24, 0x0b, 0x12, 0x22,
+0xa1, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83,
+0xe0, 0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82,
+0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3,
+0x74, 0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x22, 0xa1,
+0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x99, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5,
+0x83, 0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82,
+0x8e, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0x44, 0x80,
+0xf0, 0x12, 0x32, 0x84, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22,
+0x12, 0x10, 0x4b, 0x7f, 0x02, 0x12, 0x12, 0x61, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0,
+0xd2, 0xb1, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36,
+0xd2, 0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7e, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa,
+0x7f, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x7c, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa,
+0x7d, 0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74,
+0x40, 0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe7, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90,
+0xff, 0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43,
+0x87, 0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7e, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7f,
+0xe0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7d,
+0xe0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x18, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe7,
+0xe0, 0xf5, 0xa8, 0x02, 0x10, 0xce, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2e, 0x0d, 0x90,
+0xfa, 0xc3, 0x12, 0x1b, 0xf3, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0xf3, 0x90,
+0xfa, 0xc7, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0xea, 0xe9,
+0x24, 0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc9, 0x12, 0x1b, 0xf3, 0xab, 0x5c, 0xaa, 0x5d,
+0xa9, 0x5e, 0x12, 0x2e, 0x19, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa,
+0xc1, 0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0xee,
+0xff, 0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc6, 0x12, 0x2d, 0xee, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83,
+0xf6, 0x12, 0x2d, 0xeb, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0xf4, 0x75, 0xf0, 0x02,
+0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xc7, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1b, 0x1c, 0xab, 0x5c, 0xaa,
+0x5d, 0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0xbb, 0x30, 0xe4, 0x03, 0x12, 0x2e, 0x03, 0x78,
+0x82, 0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xc2, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58,
+0x90, 0xfa, 0xc2, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xc1, 0xf0, 0x12, 0x1a, 0xa2, 0x24, 0x6e,
+0x60, 0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0xda, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x25,
+0x56, 0x80, 0x62, 0x12, 0x2e, 0x24, 0x12, 0x1f, 0xda, 0x90, 0xfa, 0xc2, 0xef, 0xf0, 0x80, 0x55,
+0x90, 0xfa, 0xc2, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0xda, 0x60, 0x09, 0x24, 0x30, 0x70,
+0x3e, 0x12, 0x2d, 0x30, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b,
+0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2e, 0x24, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb,
+0xfd, 0x90, 0x00, 0x08, 0x12, 0x1b, 0x48, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02,
+0xd0, 0x03, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xc1, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90,
+0xfa, 0xc2, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xc2, 0xe0, 0x12, 0x2e, 0x24, 0x90, 0x00, 0x02, 0x12,
+0x1a, 0xfa, 0x90, 0xfa, 0xc1, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c,
+0xe5, 0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2e, 0x53, 0x70, 0x16, 0x12, 0x2e, 0x72, 0xe5,
+0x2d, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0xd8, 0x50, 0xf2, 0x12, 0x27, 0x25, 0x40, 0x0b, 0x7f,
+0x00, 0x22, 0x12, 0x2e, 0x72, 0x12, 0x27, 0x25, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0,
+0xe5, 0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4,
+0xf0, 0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0xc1,
+0x40, 0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff,
+0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2e, 0x65, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b,
+0xe4, 0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0xc1, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12,
+0x2e, 0x65, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0xd8, 0x12, 0x10,
+0x4b, 0x78, 0x84, 0x12, 0x23, 0x31, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x31, 0xa9, 0x02, 0x27,
+0xbc, 0x78, 0x84, 0xe6, 0xf9, 0x24, 0x13, 0x12, 0x22, 0xad, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54,
+0x03, 0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44,
+0x04, 0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80,
+0x39, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0,
+0x80, 0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef,
+0x54, 0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80,
+0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x18, 0xe0, 0x04, 0xf0,
+0xaf, 0x01, 0x12, 0x22, 0xee, 0xfd, 0x12, 0x2f, 0xe5, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce, 0x75,
+0xa8, 0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x28, 0x09, 0x02, 0x31,
+0x8c, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf,
+0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54,
+0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80,
+0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0xa9, 0xe4, 0x7e, 0x01, 0x93,
+0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60,
+0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4,
+0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3,
+0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5,
+0x22, 0x12, 0x1d, 0xc2, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x30, 0x13,
+0x12, 0x1d, 0xc2, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5,
+0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x94, 0x12, 0x1e, 0x03, 0x60, 0x2c, 0x12, 0x2d,
+0x85, 0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x94, 0x12, 0x1b, 0xcc, 0xe4,
+0xf0, 0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0xa0, 0x12, 0x1b, 0xcc, 0xe0, 0xa3,
+0x30, 0xe6, 0x33, 0x12, 0x1d, 0xc2, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90,
+0xfa, 0x98, 0x12, 0x1e, 0x03, 0x60, 0x16, 0x12, 0x2d, 0x85, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02,
+0xe5, 0x22, 0x90, 0xfa, 0x98, 0x12, 0x1b, 0xcc, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5,
+0x22, 0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe,
+0xef, 0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0,
+0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x0f, 0x12, 0x1c, 0xb0, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5,
+0x3a, 0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5,
+0x39, 0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0xdf, 0x12, 0x1e,
+0x34, 0x12, 0x1e, 0x26, 0x12, 0x1a, 0xa2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e,
+0x70, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0xbb, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f,
+0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x5e, 0x12, 0x1e, 0x3b, 0x12, 0x25, 0xfa, 0x12,
+0x1d, 0x89, 0x12, 0x1a, 0xbb, 0x60, 0x03, 0x02, 0x32, 0x7a, 0xe4, 0xff, 0x12, 0x32, 0x6e, 0x22,
+0x8b, 0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2e, 0x53, 0x70,
+0x16, 0x12, 0x2e, 0x72, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0xd8, 0x50, 0xf2, 0x12,
+0x29, 0xd5, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2e, 0x72, 0x12, 0x29, 0xd5, 0x50, 0xf8, 0xe4,
+0xf5, 0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0xc5, 0x40,
+0x03, 0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5,
+0x46, 0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0xc5, 0x40, 0x03, 0x7f,
+0x18, 0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x1a, 0xa2, 0x90, 0xff,
+0xf1, 0xf0, 0x02, 0x31, 0xd8, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0xd8, 0x7b, 0x01,
+0x7a, 0xfa, 0x79, 0xcf, 0xe4, 0xfd, 0x12, 0x23, 0x61, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x09,
+0x12, 0x1b, 0x1c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01,
+0x12, 0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xff, 0xf7,
+0xe5, 0x23, 0x12, 0x2a, 0x39, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcf, 0xe4, 0xf0,
+0xa3, 0x74, 0x06, 0x12, 0x2a, 0x39, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94,
+0xf0, 0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23,
+0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d,
+0x01, 0x02, 0x26, 0x98, 0x90, 0xff, 0x93, 0x74, 0x81, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06,
+0x90, 0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9,
+0x16, 0xf0, 0xa3, 0xf0, 0x12, 0x2b, 0x39, 0x12, 0x16, 0xc9, 0x12, 0x30, 0x69, 0x7e, 0x07, 0x7f,
+0xd0, 0x12, 0x12, 0x2a, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x12, 0x44, 0xe4, 0x78, 0x77, 0xf6, 0x78,
+0x77, 0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77,
+0x06, 0x80, 0xec, 0x7f, 0x03, 0x12, 0x30, 0xb2, 0x90, 0xf9, 0x16, 0xe0, 0x20, 0xe4, 0x05, 0x7f,
+0x04, 0x12, 0x30, 0xb2, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8,
+0xe0, 0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05,
+0x12, 0x11, 0xae, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c,
+0x76, 0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76,
+0xff, 0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76,
+0x9e, 0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x23, 0x49, 0x7b, 0x01, 0x7a,
+0xff, 0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0xe1, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08,
+0xa4, 0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x23, 0x49, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0xe1,
+0x78, 0x6d, 0xef, 0x12, 0x23, 0x49, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0,
+0xe0, 0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe6, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcf,
+0xe4, 0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x7e, 0x00, 0x90, 0xfa, 0xe4, 0xee,
+0xf0, 0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcf, 0xe0, 0xb4, 0x52, 0x09, 0x90,
+0xf9, 0x16, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe4, 0xe0, 0x70, 0x04, 0xa3, 0xe0,
+0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcf, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x16, 0xe0, 0x44,
+0x10, 0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe6, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x54, 0xef,
+0xf0, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x03, 0x68, 0x01, 0xff, 0x48, 0x03, 0x6b,
+0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x98, 0x00, 0x00, 0x00, 0x00, 0x44, 0xfa,
+0x94, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xb2, 0x00, 0x00, 0x42, 0xfa, 0x7e, 0x00, 0x00, 0x42,
+0xfa, 0x7c, 0x00, 0x00, 0x42, 0xf9, 0x6d, 0xff, 0xff, 0x42, 0xfa, 0x7a, 0x00, 0x00, 0x41, 0xf9,
+0x66, 0xff, 0x41, 0xf9, 0x1c, 0x19, 0x41, 0xf9, 0x15, 0x00, 0x43, 0xf9, 0x19, 0x0a, 0x32, 0x02,
+0x41, 0xf9, 0x68, 0x20, 0x41, 0xf9, 0x69, 0x20, 0x41, 0xf9, 0x65, 0x00, 0x41, 0xf9, 0x67, 0x00,
+0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9, 0x16, 0x00, 0x00, 0x41, 0xf9, 0x18, 0x00,
+0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 0x10, 0x4b, 0x78, 0x8a, 0xef, 0xf6, 0x12,
+0x2a, 0xc7, 0x12, 0x22, 0xee, 0x30, 0xe0, 0x29, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x54, 0x7f,
+0xf0, 0x78, 0x6b, 0x12, 0x1b, 0xd8, 0x90, 0x00, 0x02, 0x12, 0x1a, 0xbb, 0x30, 0xe7, 0x09, 0x90,
+0x00, 0x02, 0xe4, 0x12, 0x1a, 0xfa, 0x80, 0xe9, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x44, 0x80,
+0xf0, 0x12, 0x22, 0xee, 0x30, 0xe1, 0x1e, 0x12, 0x22, 0x97, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x32,
+0x19, 0x78, 0x68, 0x12, 0x1b, 0xd8, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0xfa, 0x12, 0x22,
+0x97, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x32, 0x84, 0xe4, 0xff, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce,
+0x12, 0x10, 0x4b, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x31, 0x50, 0x12, 0x31, 0xa9, 0x78, 0x85, 0xe6,
+0xff, 0x24, 0x13, 0x12, 0x22, 0xad, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90,
+0xff, 0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80,
+0x19, 0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20,
+0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x18, 0xe0, 0x14, 0xf0,
+0xe0, 0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0xce, 0x12, 0x1e, 0x1c, 0xe5, 0x3a, 0x64, 0x09, 0x70,
+0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00,
+0x40, 0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5,
+0x39, 0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1e, 0x34, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12,
+0x1c, 0xc1, 0x12, 0x1a, 0xa2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83,
+0xed, 0xf0, 0x0e, 0x12, 0x1c, 0xb0, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22,
+0x8b, 0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2e, 0x19, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22,
+0xab, 0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2e, 0x0d, 0x90, 0xfa, 0xc9, 0x12, 0x1b, 0xf3, 0xe5,
+0x5b, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0xf3, 0xe4, 0x90,
+0xfa, 0xc2, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xc1, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f,
+0x50, 0x12, 0x12, 0x2d, 0xeb, 0xff, 0x12, 0x2d, 0xf4, 0x12, 0x2e, 0x07, 0x78, 0x8b, 0x06, 0x12,
+0x2e, 0x03, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x32, 0x0a, 0xe4, 0x93, 0xff, 0x78,
+0x74, 0xf6, 0x54, 0x0f, 0x12, 0x1d, 0xa8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c,
+0xd9, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6,
+0xee, 0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f,
+0x00, 0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed,
+0xf0, 0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58,
+0x90, 0x00, 0x03, 0x12, 0x1a, 0xbb, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc9, 0x12, 0x1b,
+0xea, 0x02, 0x1a, 0xa2, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0xea, 0xef, 0x12, 0x1a, 0xe8, 0x90, 0xfa,
+0xca, 0xe4, 0x22, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1b, 0x1c, 0x90, 0x00, 0x08,
+0x12, 0x1b, 0x48, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb, 0x90,
+0xfa, 0xc1, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xdd, 0xe0, 0xff,
+0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xd7, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd6, 0xe0, 0x9e, 0xf0, 0x90,
+0xfa, 0xd8, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50,
+0xf5, 0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa,
+0xe6, 0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02,
+0x1a, 0xe8, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64,
+0xb4, 0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0xef, 0x7f, 0x02, 0x02, 0x31, 0xef, 0xaf, 0x64, 0x12,
+0x2a, 0xc7, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1d, 0x33,
+0xe0, 0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12,
+0x31, 0xef, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0xef, 0x30, 0x09, 0x07, 0x12, 0x1d, 0x33, 0xe0,
+0x44, 0x80, 0xf0, 0x12, 0x32, 0x84, 0x22, 0x12, 0x10, 0x4b, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60,
+0xf0, 0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7,
+0x13, 0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44,
+0x01, 0xf0, 0x80, 0x0d, 0x12, 0x1d, 0xdf, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe,
+0xf0, 0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xde, 0x12, 0x1d, 0xe7, 0x02, 0x10,
+0xce, 0x12, 0x10, 0x4b, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0xc7, 0x90, 0xf9, 0x6a,
+0x12, 0x1b, 0xea, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe,
+0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0xd3, 0x12, 0x32,
+0x84, 0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x87, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce, 0x8f, 0x63,
+0x12, 0x2a, 0xc7, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04,
+0x12, 0x22, 0xa1, 0xe0, 0x54, 0x3f, 0xf0, 0x12, 0x23, 0x41, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0,
+0x54, 0xf8, 0xf0, 0x12, 0x32, 0x84, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 0x7f,
+0x00, 0x22, 0x12, 0x10, 0x4b, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xfa, 0x24, 0x06, 0x12, 0x22, 0x9f,
+0xe0, 0xfd, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x03, 0x12, 0x23, 0x02, 0x24, 0x05, 0x12, 0x22, 0xa1,
+0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0xfa, 0x12, 0x32, 0x84, 0x7d, 0x02, 0xe4, 0xff, 0x12, 0x2f,
+0xb4, 0x02, 0x10, 0xce, 0xae, 0x05, 0x12, 0x1d, 0x8e, 0xef, 0x12, 0x1a, 0xfa, 0x0e, 0x0e, 0x0e,
+0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee, 0xd3, 0x94, 0x08, 0x74,
+0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 0x12, 0x1a, 0xfa, 0xaf,
+0x06, 0x12, 0x32, 0x6e, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 0x60, 0x03, 0x7f, 0x10,
+0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 0x74, 0x6e, 0x2e, 0xf8,
+0x74, 0x02, 0x46, 0xf6, 0x74, 0x99, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xed, 0xf0,
+0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 0x7c, 0xff, 0x7d, 0xe2,
+0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0,
+0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 0x10,
+0x4b, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x16, 0x90, 0xff, 0x83,
+0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00, 0x40, 0x05, 0x12, 0x28,
+0xd7, 0x80, 0x03, 0x12, 0x32, 0x7a, 0x02, 0x10, 0xce, 0x90, 0xff, 0xfc, 0xe0, 0x20, 0xe7, 0x1f,
+0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 0x7f, 0x00, 0xef, 0x1f,
+0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0x80, 0xef, 0x22,
+0x12, 0x10, 0x4b, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 0x12, 0x30, 0xe1, 0x0f,
+0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x61, 0x12, 0x1d, 0xf6, 0x02,
+0x10, 0xce, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xc0, 0x78, 0x7e, 0x12, 0x23,
+0x42, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x32, 0x84, 0xaf, 0x23, 0x12,
+0x13, 0x87, 0x22, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f, 0x70, 0x02, 0x15,
+0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 0x12, 0x10, 0x24,
+0x80, 0xe5, 0x22, 0x11, 0xdc, 0x2e, 0xc7, 0x24, 0xb0, 0x32, 0x60, 0x30, 0x90, 0x30, 0x3e, 0x31,
+0x6f, 0x2f, 0x82, 0x27, 0x2e, 0x2c, 0x80, 0x31, 0x12, 0x31, 0x31, 0x1e, 0x64, 0x2f, 0x11, 0x2c,
+0x18, 0x0e, 0x12, 0x10, 0x4b, 0x78, 0x86, 0x12, 0x23, 0x31, 0x20, 0xe1, 0x07, 0x7f, 0x12, 0x12,
+0x31, 0xa9, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x24, 0x0a, 0x12, 0x31, 0xa9, 0x02, 0x10,
+0xce, 0x12, 0x10, 0x4b, 0x78, 0x87, 0x12, 0x23, 0x31, 0x20, 0xe2, 0x07, 0x7f, 0x11, 0x12, 0x31,
+0xa9, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2f, 0x4e, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce,
+0x8f, 0x61, 0x12, 0x2f, 0x4e, 0xaf, 0x61, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xc0, 0x12, 0x32, 0x84,
+0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13, 0x87, 0x22, 0x12,
+0x10, 0x4b, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x05, 0x12, 0x2c,
+0xd8, 0x80, 0x06, 0x12, 0x1e, 0x14, 0x12, 0x1e, 0x1c, 0x02, 0x10, 0xce, 0x12, 0x2a, 0x54, 0x12,
+0x13, 0x03, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12, 0xa0, 0x12, 0x29,
+0xde, 0x12, 0x13, 0x3f, 0x12, 0x11, 0xbc, 0x80, 0xe3, 0x12, 0x1d, 0x8e, 0xef, 0x12, 0x1a, 0xfa,
+0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x32, 0x7a, 0xe4, 0xff, 0x12, 0x32, 0x6e,
+0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff,
+0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0x28, 0x60,
+0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0xef,
+0x30, 0xe7, 0x08, 0x12, 0x1d, 0x45, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 0x1d, 0x98, 0xe0,
+0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 0x40, 0x00, 0x40,
+0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22, 0xb7, 0xa3, 0xa3,
+0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 0x3b, 0x39, 0x85,
+0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe4,
+0xfe, 0xee, 0x90, 0x32, 0x04, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 0x07, 0xf2, 0xc3,
+0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x90, 0x0a, 0x02, 0x00, 0x00, 0x11, 0x13, 0x00,
+0x12, 0x10, 0x4b, 0x7f, 0x02, 0x12, 0x10, 0xda, 0x12, 0x1d, 0xf6, 0x02, 0x10, 0xce, 0x75, 0x39,
+0x00, 0x8f, 0x3a, 0x12, 0x1c, 0xe0, 0x12, 0x2c, 0xd8, 0x22, 0x12, 0x1e, 0x1c, 0x12, 0x1d, 0xdf,
+0x12, 0x1e, 0x14, 0x22, 0xc2, 0x08, 0x22,
 };
 
 #undef IMAGE_VERSION_NAME
index 544098d2b775178651ebeccdb2ec4893ca42da2e..0d3903691e8c4a03a048c0c65e8c064e2ed52a49 100644 (file)
@@ -48,7 +48,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.7"
+#define DRIVER_VERSION "v0.7mode043006"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
 #define DRIVER_DESC "Edgeport USB Serial Driver"
 
@@ -173,8 +173,12 @@ static struct usb_device_id edgeport_2port_id_table [] = {
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) },
-// The 4-port shows up as two 2-port devices
+       /* The 4, 8 and 16 port devices show up as multiple 2 port devices */
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
        { }
 };
 
@@ -209,6 +213,10 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
        { }
 };
 
@@ -231,6 +239,7 @@ static int TIStayInBootMode = 0;
 static int low_latency = EDGE_LOW_LATENCY;
 static int closing_wait = EDGE_CLOSING_WAIT;
 static int ignore_cpu_rev = 0;
+static int default_uart_mode = 0;      /* RS232 */
 
 
 static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length);
@@ -241,6 +250,10 @@ static int restart_read(struct edgeport_port *edge_port);
 static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
 static void edge_send(struct usb_serial_port *port);
 
+/* sysfs attributes */
+static int edge_create_sysfs_attrs(struct usb_serial_port *port);
+static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
+
 /* circular buffer */
 static struct edge_buf *edge_buf_alloc(unsigned int size);
 static void edge_buf_free(struct edge_buf *eb);
@@ -1706,13 +1719,14 @@ static void edge_interrupt_callback (struct urb *urb)
        int length = urb->actual_length;
        int port_number;
        int function;
-       int status;
+       int retval;
        __u8 lsr;
        __u8 msr;
+       int status = urb->status;
 
        dbg("%s", __FUNCTION__);
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -1720,10 +1734,12 @@ static void edge_interrupt_callback (struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d",
+                   __FUNCTION__, status);
                return;
        default:
-               dev_err(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __FUNCTION__, urb->status);
+               dev_err(&urb->dev->dev, "%s - nonzero urb status received: "
+                       "%d\n", __FUNCTION__, status);
                goto exit;
        }
 
@@ -1781,10 +1797,10 @@ static void edge_interrupt_callback (struct urb *urb)
        }
 
 exit:
-       status = usb_submit_urb (urb, GFP_ATOMIC);
-       if (status)
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval)
                dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
-                        __FUNCTION__, status);
+                        __FUNCTION__, retval);
 }
 
 static void edge_bulk_in_callback (struct urb *urb)
@@ -1792,12 +1808,13 @@ static void edge_bulk_in_callback (struct urb *urb)
        struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
        unsigned char *data = urb->transfer_buffer;
        struct tty_struct *tty;
-       int status = 0;
+       int retval = 0;
        int port_number;
+       int status = urb->status;
 
        dbg("%s", __FUNCTION__);
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -1805,17 +1822,18 @@ static void edge_bulk_in_callback (struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d",
+                   __FUNCTION__, status);
                return;
        default:
                dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n",
-                    __FUNCTION__, urb->status );
+                    __FUNCTION__, status);
        }
 
-       if (urb->status == -EPIPE)
+       if (status == -EPIPE)
                goto exit;
 
-       if (urb->status) {
+       if (status) {
                dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__);
                return;
        }
@@ -1849,14 +1867,14 @@ exit:
        spin_lock(&edge_port->ep_lock);
        if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) {
                urb->dev = edge_port->port->serial->dev;
-               status = usb_submit_urb(urb, GFP_ATOMIC);
+               retval = usb_submit_urb(urb, GFP_ATOMIC);
        } else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING) {
                edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPED;
        }
        spin_unlock(&edge_port->ep_lock);
-       if (status)
+       if (retval)
                dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
-                        __FUNCTION__, status);
+                        __FUNCTION__, retval);
 }
 
 static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
@@ -1883,12 +1901,13 @@ static void edge_bulk_out_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+       int status = urb->status;
 
        dbg ("%s - port %d", __FUNCTION__, port->number);
 
        edge_port->ep_write_urb_in_use = 0;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -1896,11 +1915,12 @@ static void edge_bulk_out_callback (struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d",
+                   __FUNCTION__, status);
                return;
        default:
-               dev_err (&urb->dev->dev,"%s - nonzero write bulk status received: %d\n",
-                    __FUNCTION__, urb->status);
+               dev_err(&urb->dev->dev, "%s - nonzero write bulk status "
+                       "received: %d\n", __FUNCTION__, status);
        }
 
        /* send any buffered data */
@@ -2351,7 +2371,7 @@ static int restart_read(struct edgeport_port *edge_port)
                urb->complete = edge_bulk_in_callback;
                urb->context = edge_port;
                urb->dev = edge_port->port->serial->dev;
-               status = usb_submit_urb(urb, GFP_KERNEL);
+               status = usb_submit_urb(urb, GFP_ATOMIC);
        }
        edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING;
        edge_port->shadow_mcr |= MCR_RTS;
@@ -2524,14 +2544,6 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
        }
 
        cflag = tty->termios->c_cflag;
-       /* check that they really want us to change something */
-       if (old_termios) {
-               if (cflag == old_termios->c_cflag &&
-                   tty->termios->c_iflag == old_termios->c_iflag) {
-                       dbg ("%s - nothing to change", __FUNCTION__);
-                       return;
-               }
-       }
 
        dbg("%s - clfag %08x iflag %08x", __FUNCTION__, 
            tty->termios->c_cflag, tty->termios->c_iflag);
@@ -2758,7 +2770,7 @@ static int edge_startup (struct usb_serial *serial)
                edge_port->port = serial->port[i];
                edge_port->edge_serial = edge_serial;
                usb_set_serial_port_data(serial->port[i], edge_port);
-               edge_port->bUartMode = 0;       /* Default is RS232 */
+               edge_port->bUartMode = default_uart_mode;
        }
        
        return 0;
@@ -2784,6 +2796,7 @@ static void edge_shutdown (struct usb_serial *serial)
 
        for (i=0; i < serial->num_ports; ++i) {
                edge_port = usb_get_serial_port_data(serial->port[i]);
+               edge_remove_sysfs_attrs(edge_port->port);
                if (edge_port) {
                        edge_buf_free(edge_port->ep_out_buf);
                        kfree(edge_port);
@@ -2795,6 +2808,48 @@ static void edge_shutdown (struct usb_serial *serial)
 }
 
 
+/* Sysfs Attributes */
+
+static ssize_t show_uart_mode(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct usb_serial_port *port = to_usb_serial_port(dev);
+       struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+
+       return sprintf(buf, "%d\n", edge_port->bUartMode);
+}
+
+static ssize_t store_uart_mode(struct device *dev,
+       struct device_attribute *attr, const char *valbuf, size_t count)
+{
+       struct usb_serial_port *port = to_usb_serial_port(dev);
+       struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+       unsigned int v = simple_strtoul(valbuf, NULL, 0);
+
+       dbg("%s: setting uart_mode = %d", __FUNCTION__, v);
+
+       if (v < 256)
+               edge_port->bUartMode = v;
+       else
+               dev_err(dev, "%s - uart_mode %d is invalid\n", __FUNCTION__, v);
+
+       return count;
+}
+
+static DEVICE_ATTR(uart_mode, S_IWUSR | S_IRUGO, show_uart_mode, store_uart_mode);
+
+static int edge_create_sysfs_attrs(struct usb_serial_port *port)
+{
+       return device_create_file(&port->dev, &dev_attr_uart_mode);
+}
+
+static int edge_remove_sysfs_attrs(struct usb_serial_port *port)
+{
+       device_remove_file(&port->dev, &dev_attr_uart_mode);
+       return 0;
+}
+
+
 /* Circular Buffer */
 
 /*
@@ -2991,6 +3046,7 @@ static struct usb_serial_driver edgeport_1port_device = {
        .unthrottle             = edge_unthrottle,
        .attach                 = edge_startup,
        .shutdown               = edge_shutdown,
+       .port_probe             = edge_create_sysfs_attrs,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -3022,6 +3078,7 @@ static struct usb_serial_driver edgeport_2port_device = {
        .unthrottle             = edge_unthrottle,
        .attach                 = edge_startup,
        .shutdown               = edge_shutdown,
+       .port_probe             = edge_create_sysfs_attrs,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -3085,3 +3142,6 @@ MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs");
 module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device");
 
+module_param(default_uart_mode, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(default_uart_mode, "Default uart_mode, 0=RS232, ...");
+
index e57fa117e48639abf58a71fce3e92d0b66e7b7fd..8e1a491e52a99d72f84ddf5a72d2f5e642b0be2d 100644 (file)
 #define ION_DEVICE_ID_TI_EDGEPORT_2I           0x0207  // Edgeport/2i RS422/RS485
 #define ION_DEVICE_ID_TI_EDGEPORT_421          0x020C  // Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port)
 #define ION_DEVICE_ID_TI_EDGEPORT_21           0x020D  // Edgeport/21 2 RS232 + Parallel (lucent on a different hub port)
-#define ION_DEVICE_ID_TI_EDGEPORT_8            0x020F  // Edgeport/8 (single-CPU)
+#define ION_DEVICE_ID_TI_EDGEPORT_416          0x0212  // Edgeport/416
 #define ION_DEVICE_ID_TI_EDGEPORT_1            0x0215  // Edgeport/1 RS232
 #define ION_DEVICE_ID_TI_EDGEPORT_42           0x0217  // Edgeport/42 4 hub 2 RS232
 #define ION_DEVICE_ID_TI_EDGEPORT_22I                  0x021A  // Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232
 #define ION_DEVICE_ID_TI_EDGEPORT_21C          0x021E  // Edgeport/21c is a TI based Edgeport/2 with lucent chip
 
 // Generation 3 devices -- 3410 based edgport/1 (256 byte I2C) 
-#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1     0x240   // Edgeport/1 RS232
-#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I    0x241   // Edgeport/1i- RS422 model
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1     0x0240  // Edgeport/1 RS232
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I    0x0241  // Edgeport/1i- RS422 model
 
 // Ti based software switchable RS232/RS422/RS485 devices
-#define ION_DEVICE_ID_TI_EDGEPORT_4S           0x242   // Edgeport/4s - software switchable model
-#define ION_DEVICE_ID_IT_EDGEPORT_8S           0x243   // Edgeport/8s - software switchable model
+#define ION_DEVICE_ID_TI_EDGEPORT_4S           0x0242  // Edgeport/4s - software switchable model
+#define ION_DEVICE_ID_TI_EDGEPORT_8S           0x0243  // Edgeport/8s - software switchable model
+#define ION_DEVICE_ID_TI_EDGEPORT_8            0x0244  // Edgeport/8 (single-CPU)
+#define ION_DEVICE_ID_TI_EDGEPORT_416B         0x0247  // Edgeport/416
 
 
 /************************************************************************
index 4df0ec74e0b1c0c908d3cc45852296933c98ca55..0455c1552ae90e9e00dde3f8bc52bd63625c66f4 100644 (file)
@@ -732,11 +732,13 @@ static void ipaq_read_bulk_callback(struct urb *urb)
        struct tty_struct       *tty;
        unsigned char           *data = urb->transfer_buffer;
        int                     result;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
@@ -870,11 +872,13 @@ static void ipaq_write_bulk_callback(struct urb *urb)
        struct ipaq_private     *priv = usb_get_serial_port_data(port);
        unsigned long           flags;
        int                     result;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
-       
-       if (urb->status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+
+       if (status) {
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
index 1bc586064c771b3c70a141b52b64d8e2a6fd8ce2..1b94daa615845f50f185328b2ecf3326f71bdffa 100644 (file)
@@ -167,11 +167,13 @@ static void ipw_read_bulk_callback(struct urb *urb)
        unsigned char *data = urb->transfer_buffer;
        struct tty_struct *tty;
        int result;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
@@ -369,13 +371,15 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
 static void ipw_write_bulk_callback(struct urb *urb)
 {
        struct usb_serial_port *port = urb->context;
+       int status = urb->status;
 
        dbg("%s", __FUNCTION__);
 
        port->write_urb_busy = 0;
 
-       if (urb->status)
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+       if (status)
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, status);
 
        usb_serial_port_softint(port);
 }
index 9d847f69291cacb69aac6816cca2c24a2078e4c0..5ab6a0c5ac52c3fbb663ee4989338490988c779c 100644 (file)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * 2007_Jun_21  Alan Cox <alan@redhat.com>
+ *     Minimal cleanups for some of the driver problens and tty layer abuse.
+ *     Still needs fixing to allow multiple dongles.
+ *
  * 2002_Mar_07 greg kh
  *     moved some needed structures and #define values from the
  *     net/irda/irda-usb.h file into our file, as we don't want to depend on
@@ -109,6 +113,7 @@ static void ir_write_bulk_callback (struct urb *urb);
 static void ir_read_bulk_callback (struct urb *urb);
 static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
 
+/* Not that this lot means you can only have one per system */
 static u8 ir_baud = 0;
 static u8 ir_xbof = 0;
 static u8 ir_add_bof = 0;
@@ -392,12 +397,14 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
 static void ir_write_bulk_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
        port->write_urb_busy = 0;
-       if (urb->status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
@@ -417,6 +424,7 @@ static void ir_read_bulk_callback (struct urb *urb)
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
        int result;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -425,8 +433,7 @@ static void ir_read_bulk_callback (struct urb *urb)
                return;
        }
 
-       switch (urb->status) {
-
+       switch (status) {
                case 0: /* Successful */
 
                        /*
@@ -444,22 +451,12 @@ static void ir_read_bulk_callback (struct urb *urb)
                                urb->actual_length,
                                data);
 
-                       /*
-                        * Bypass flip-buffers, and feed the ldisc directly
-                        * due to our potentially large buffer size.  Since we
-                        * used to set low_latency, this is exactly what the
-                        * tty layer did anyway :)
-                        */
                        tty = port->tty;
 
-                       /*
-                        *      FIXME: must not do this in IRQ context
-                        */
-                       tty->ldisc.receive_buf(
-                               tty,
-                               data+1,
-                               NULL,
-                               urb->actual_length-1);
+                       if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
+                               tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
+                               tty_flip_buffer_push(tty);
+                       }
 
                        /*
                         * No break here.
@@ -490,7 +487,7 @@ static void ir_read_bulk_callback (struct urb *urb)
                default:
                        dbg("%s - nonzero read bulk status received: %d",
                                __FUNCTION__, 
-                               urb->status);
+                               status);
                        break ;
 
        }
@@ -501,8 +498,9 @@ static void ir_read_bulk_callback (struct urb *urb)
 static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 {
        unsigned char *transfer_buffer;
-       unsigned int cflag;
        int result;
+       speed_t baud;
+       int ir_baud;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -511,77 +509,59 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
                return;
        }
 
-       cflag = port->tty->termios->c_cflag;
-       /* check that they really want us to change something */
-       if (old_termios) {
-               if ((cflag == old_termios->c_cflag) &&
-                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-                       dbg("%s - nothing to change...", __FUNCTION__);
-                       return;
-               }
+       baud = tty_get_baud_rate(port->tty);
+
+       /*
+        * FIXME, we should compare the baud request against the
+        * capability stated in the IR header that we got in the
+        * startup function.
+        */
+
+       switch (baud) {
+               case 2400:      ir_baud = SPEED_2400; break;
+               case 9600:      ir_baud = SPEED_9600; break;
+               case 19200:     ir_baud = SPEED_19200; break;
+               case 38400:     ir_baud = SPEED_38400; break;
+               case 57600:     ir_baud = SPEED_57600; break;
+               case 115200:    ir_baud = SPEED_115200; break;
+               case 576000:    ir_baud = SPEED_576000; break;
+               case 1152000:   ir_baud = SPEED_1152000; break;
+               case 4000000:   ir_baud = SPEED_4000000; break;
+                       break;
+               default:
+                       ir_baud = SPEED_9600;
+                       baud = 9600;
+                       /* And once the new tty stuff is all done we need to
+                          call back to correct the baud bits */
        }
 
-       /* All we can change is the baud rate */
-       if (cflag & CBAUD) {
-
-               dbg ("%s - asking for baud %d",
-                       __FUNCTION__,
-                       tty_get_baud_rate(port->tty));
-
-               /* 
-                * FIXME, we should compare the baud request against the
-                * capability stated in the IR header that we got in the
-                * startup function.
-                */
-               switch (cflag & CBAUD) {
-                       case B2400:    ir_baud = SPEED_2400;    break;
-                       default:
-                       case B9600:    ir_baud = SPEED_9600;    break;
-                       case B19200:   ir_baud = SPEED_19200;   break;
-                       case B38400:   ir_baud = SPEED_38400;   break;
-                       case B57600:   ir_baud = SPEED_57600;   break;
-                       case B115200:  ir_baud = SPEED_115200;  break;
-                       case B576000:  ir_baud = SPEED_576000;  break;
-                       case B1152000: ir_baud = SPEED_1152000; break;
-#ifdef B4000000
-                       case B4000000: ir_baud = SPEED_4000000; break;
-#endif
-               }
+       if (xbof == -1)
+               ir_xbof = ir_xbof_change(ir_add_bof);
+       else
+               ir_xbof = ir_xbof_change(xbof) ;
 
-               if (xbof == -1) {
-                       ir_xbof = ir_xbof_change(ir_add_bof);
-               } else {
-                       ir_xbof = ir_xbof_change(xbof) ;
-               }
+       /* FIXME need to check to see if our write urb is busy right
+        * now, or use a urb pool.
+        *
+        * send the baud change out on an "empty" data packet
+        */
+       transfer_buffer = port->write_urb->transfer_buffer;
+       *transfer_buffer = ir_xbof | ir_baud;
 
-               /* Notify the tty driver that the termios have changed. */
-               port->tty->ldisc.set_termios(port->tty, NULL);
-
-               /* FIXME need to check to see if our write urb is busy right
-                * now, or use a urb pool.
-                *
-                * send the baud change out on an "empty" data packet
-                */
-               transfer_buffer = port->write_urb->transfer_buffer;
-               *transfer_buffer = ir_xbof | ir_baud;
-
-               usb_fill_bulk_urb (
-                       port->write_urb,
-                       port->serial->dev,
-                       usb_sndbulkpipe(port->serial->dev,
-                               port->bulk_out_endpointAddress),
-                       port->write_urb->transfer_buffer,
-                       1,
-                       ir_write_bulk_callback,
-                       port);
-
-               port->write_urb->transfer_flags = URB_ZERO_PACKET;
-
-               result = usb_submit_urb (port->write_urb, GFP_KERNEL);
-               if (result)
-                       dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
-       }
-       return;
+       usb_fill_bulk_urb (
+               port->write_urb,
+               port->serial->dev,
+               usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
+               port->write_urb->transfer_buffer,
+               1,
+               ir_write_bulk_callback,
+               port);
+
+       port->write_urb->transfer_flags = URB_ZERO_PACKET;
+
+       result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+       if (result)
+               dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
 }
 
 
index e6966f12ed5aacdace21a8d14fe79d649f09e406..f2a6fce5de1e9fe688b32004364e8589a1f0e8e3 100644 (file)
@@ -115,12 +115,13 @@ static int debug;
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.1.4"
+#define DRIVER_VERSION "v1.1.5"
 #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
 #define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
 
 #define INSTAT_BUFLEN  32
 #define GLOCONT_BUFLEN 64
+#define INDAT49W_BUFLEN        512
 
        /* Per device and per port private data */
 struct keyspan_serial_private {
@@ -129,9 +130,15 @@ struct keyspan_serial_private {
        struct urb      *instat_urb;
        char            instat_buf[INSTAT_BUFLEN];
 
+       /* added to support 49wg, where data from all 4 ports comes in on 1 EP */
+       /* and high-speed supported */
+       struct urb      *indat_urb;
+       char            indat_buf[INDAT49W_BUFLEN];
+
        /* XXX this one probably will need a lock */
        struct urb      *glocont_urb;
        char            glocont_buf[GLOCONT_BUFLEN];
+       char            ctrl_buf[8];                    // for EP0 control message
 };
 
 struct keyspan_port_private {
@@ -179,12 +186,13 @@ struct keyspan_port_private {
 
        
 /* Include Keyspan message headers.  All current Keyspan Adapters
-   make use of one of four message formats which are referred
-   to as USA-26, USA-28 and USA-49, USA-90 by Keyspan and within this driver. */
+   make use of one of five message formats which are referred
+   to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */
 #include "keyspan_usa26msg.h"
 #include "keyspan_usa28msg.h"
 #include "keyspan_usa49msg.h"
 #include "keyspan_usa90msg.h"
+#include "keyspan_usa67msg.h"
        
 
 /* Functions used by new usb-serial code. */
@@ -419,14 +427,15 @@ static void       usa26_indat_callback(struct urb *urb)
        struct usb_serial_port  *port;
        struct tty_struct       *tty;
        unsigned char           *data = urb->transfer_buffer;
+       int status = urb->status;
 
        dbg ("%s", __FUNCTION__); 
 
        endpoint = usb_pipeendpoint(urb->pipe);
 
-       if (urb->status) {
+       if (status) {
                dbg("%s - nonzero status: %x on endpoint %d.",
-                   __FUNCTION__, urb->status, endpoint);
+                   __FUNCTION__, status, endpoint);
                return;
        }
 
@@ -511,11 +520,12 @@ static void       usa26_instat_callback(struct urb *urb)
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
        int old_dcd_state, err;
+       int status = urb->status;
 
        serial = (struct usb_serial *) urb->context;
 
-       if (urb->status) {
-               dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero status: %x", __FUNCTION__, status);
                return;
        }
        if (urb->actual_length != 9) {
@@ -579,6 +589,7 @@ static void usa28_indat_callback(struct urb *urb)
        struct tty_struct       *tty;
        unsigned char           *data;
        struct keyspan_port_private             *p_priv;
+       int status = urb->status;
 
        dbg ("%s", __FUNCTION__);
 
@@ -590,9 +601,9 @@ static void usa28_indat_callback(struct urb *urb)
                return;
 
        do {
-               if (urb->status) {
+               if (status) {
                        dbg("%s - nonzero status: %x on endpoint %d.",
-                           __FUNCTION__, urb->status, usb_pipeendpoint(urb->pipe));
+                           __FUNCTION__, status, usb_pipeendpoint(urb->pipe));
                        return;
                }
 
@@ -648,11 +659,12 @@ static void       usa28_instat_callback(struct urb *urb)
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
        int old_dcd_state;
+       int status = urb->status;
 
        serial = (struct usb_serial *) urb->context;
 
-       if (urb->status) {
-               dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero status: %x", __FUNCTION__, status);
                return;
        }
 
@@ -739,13 +751,14 @@ static void       usa49_instat_callback(struct urb *urb)
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
        int old_dcd_state;
+       int status = urb->status;
 
        dbg ("%s", __FUNCTION__);
 
        serial = (struct usb_serial *) urb->context;
 
-       if (urb->status) {
-               dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero status: %x", __FUNCTION__, status);
                return;
        }
 
@@ -805,14 +818,15 @@ static void       usa49_indat_callback(struct urb *urb)
        struct usb_serial_port  *port;
        struct tty_struct       *tty;
        unsigned char           *data = urb->transfer_buffer;
+       int status = urb->status;
 
        dbg ("%s", __FUNCTION__);
 
        endpoint = usb_pipeendpoint(urb->pipe);
 
-       if (urb->status) {
+       if (status) {
                dbg("%s - nonzero status: %x on endpoint %d.", __FUNCTION__,
-                   urb->status, endpoint);
+                   status, endpoint);
                return;
        }
 
@@ -850,13 +864,90 @@ static void       usa49_indat_callback(struct urb *urb)
                }
 }
 
+static void usa49wg_indat_callback(struct urb *urb)
+{
+       int                     i, len, x, err;
+       struct usb_serial       *serial;
+       struct usb_serial_port  *port;
+       struct tty_struct       *tty;
+       unsigned char           *data = urb->transfer_buffer;
+       int status = urb->status;
+
+       dbg ("%s", __FUNCTION__);
+
+       serial = urb->context;
+
+       if (status) {
+               dbg("%s - nonzero status: %x", __FUNCTION__, status);
+               return;
+       }
+
+       /* inbound data is in the form P#, len, status, data */
+       i = 0;
+       len = 0;
+
+       if (urb->actual_length) {
+               while (i < urb->actual_length) {
+
+                       /* Check port number from message*/
+                       if (data[i] >= serial->num_ports) {
+                               dbg ("%s - Unexpected port number %d",
+                                       __FUNCTION__, data[i]);
+                               return;
+                       }
+                       port = serial->port[data[i++]];
+                       tty = port->tty;
+                       len = data[i++];
+
+                       /* 0x80 bit is error flag */
+                       if ((data[i] & 0x80) == 0) {
+                               /* no error on any byte */
+                               i++;
+                               for (x = 1; x < len ; ++x)
+                                       if (port->open_count)
+                                               tty_insert_flip_char(tty,
+                                                               data[i++], 0);
+                                       else
+                                               i++;
+                       } else {
+                               /*
+                                * some bytes had errors, every byte has status
+                                */
+                               for (x = 0; x + 1 < len; x += 2) {
+                                       int stat = data[i], flag = 0;
+                                       if (stat & RXERROR_OVERRUN)
+                                               flag |= TTY_OVERRUN;
+                                       if (stat & RXERROR_FRAMING)
+                                               flag |= TTY_FRAME;
+                                       if (stat & RXERROR_PARITY)
+                                               flag |= TTY_PARITY;
+                                       /* XXX should handle break (0x10) */
+                                       if (port->open_count)
+                                               tty_insert_flip_char(tty,
+                                                       data[i+1], flag);
+                                       i += 2;
+                               }
+                       }
+                       if (port->open_count)
+                               tty_flip_buffer_push(tty);
+               }
+       }
+
+       /* Resubmit urb so we continue receiving */
+       urb->dev = serial->dev;
+
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (err != 0)
+               dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+}
+
 /* not used, usa-49 doesn't have per-port control endpoints */
-static void    usa49_outcont_callback(struct urb *urb)
+static void usa49_outcont_callback(struct urb *urb)
 {
        dbg ("%s", __FUNCTION__);
 }
 
-static void    usa90_indat_callback(struct urb *urb)
+static void usa90_indat_callback(struct urb *urb)
 {
        int                     i, err;
        int                     endpoint;
@@ -864,15 +955,15 @@ static void       usa90_indat_callback(struct urb *urb)
        struct keyspan_port_private             *p_priv;
        struct tty_struct       *tty;
        unsigned char           *data = urb->transfer_buffer;
+       int status = urb->status;
 
        dbg ("%s", __FUNCTION__); 
 
        endpoint = usb_pipeendpoint(urb->pipe);
 
-
-       if (urb->status) {
+       if (status) {
                dbg("%s - nonzero status: %x on endpoint %d.",
-                   __FUNCTION__, urb->status, endpoint);
+                   __FUNCTION__, status, endpoint);
                return;
        }
 
@@ -938,11 +1029,12 @@ static void      usa90_instat_callback(struct urb *urb)
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
        int old_dcd_state, err;
+       int status = urb->status;
 
        serial = (struct usb_serial *) urb->context;
 
-       if (urb->status) {
-               dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero status: %x", __FUNCTION__, status);
                return;
        }
        if (urb->actual_length < 14) {
@@ -995,6 +1087,88 @@ static void       usa90_outcont_callback(struct urb *urb)
        }
 }
 
+/* Status messages from the 28xg */
+static void    usa67_instat_callback(struct urb *urb)
+{
+       int                                     err;
+       unsigned char                           *data = urb->transfer_buffer;
+       struct keyspan_usa67_portStatusMessage  *msg;
+       struct usb_serial                       *serial;
+       struct usb_serial_port                  *port;
+       struct keyspan_port_private             *p_priv;
+       int old_dcd_state;
+       int status = urb->status;
+
+       dbg ("%s", __FUNCTION__);
+
+       serial = urb->context;
+
+       if (status) {
+               dbg("%s - nonzero status: %x", __FUNCTION__, status);
+               return;
+       }
+
+       if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
+               dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
+               return;
+       }
+
+
+       /* Now do something useful with the data */
+       msg = (struct keyspan_usa67_portStatusMessage *)data;
+
+       /* Check port number from message and retrieve private data */
+       if (msg->port >= serial->num_ports) {
+               dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
+               return;
+       }
+
+       port = serial->port[msg->port];
+       p_priv = usb_get_serial_port_data(port);
+
+       /* Update handshaking pin state information */
+       old_dcd_state = p_priv->dcd_state;
+       p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
+       p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
+
+       if (port->tty && !C_CLOCAL(port->tty)
+           && old_dcd_state != p_priv->dcd_state) {
+               if (old_dcd_state)
+                       tty_hangup(port->tty);
+               /*  else */
+               /*      wake_up_interruptible(&p_priv->open_wait); */
+       }
+
+       /* Resubmit urb so we continue receiving */
+       urb->dev = serial->dev;
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (err != 0)
+               dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+}
+
+static void usa67_glocont_callback(struct urb *urb)
+{
+       struct usb_serial *serial;
+       struct usb_serial_port *port;
+       struct keyspan_port_private *p_priv;
+       int i;
+
+       dbg ("%s", __FUNCTION__);
+
+       serial = urb->context;
+       for (i = 0; i < serial->num_ports; ++i) {
+               port = serial->port[i];
+               p_priv = usb_get_serial_port_data(port);
+
+               if (p_priv->resend_cont) {
+                       dbg ("%s - sending setup", __FUNCTION__);
+                       keyspan_usa67_send_setup(serial, port,
+                                               p_priv->resend_cont - 1);
+                       break;
+               }
+       }
+}
+
 static int keyspan_write_room (struct usb_serial_port *port)
 {
        struct keyspan_port_private     *p_priv;
@@ -1311,6 +1485,11 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
                return NULL;
        }
 
+       if (endpoint == 0) {
+               /* control EP filled in when used */
+               return urb;
+       }
+
        ep_desc = find_ep(serial, endpoint);
        if (!ep_desc) {
                /* leak the urb, something's wrong and the callers don't care */
@@ -1380,6 +1559,14 @@ static struct callbacks {
                .outdat_callback =      usa2x_outdat_callback,
                .inack_callback =       usa28_inack_callback,
                .outcont_callback =     usa90_outcont_callback,
+       }, {
+               /* msg_usa67 callbacks */
+               .instat_callback =      usa67_instat_callback,
+               .glocont_callback =     usa67_glocont_callback,
+               .indat_callback =       usa26_indat_callback,
+               .outdat_callback =      usa2x_outdat_callback,
+               .inack_callback =       usa26_inack_callback,
+               .outcont_callback =     usa26_outcont_callback,
        }
 };
 
@@ -1410,6 +1597,11 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
                 serial, s_priv->instat_buf, INSTAT_BUFLEN,
                 cback->instat_callback);
 
+       s_priv->indat_urb = keyspan_setup_urb
+               (serial, d_details->indat_endpoint, USB_DIR_IN,
+                serial, s_priv->indat_buf, INDAT49W_BUFLEN,
+                usa49wg_indat_callback);
+
        s_priv->glocont_urb = keyspan_setup_urb
                (serial, d_details->glocont_endpoint, USB_DIR_OUT,
                 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
@@ -1685,8 +1877,8 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
        }
 
        /* Save reset port val for resend.
-       Don't overwrite resend for close condition. */
-       if (p_priv->resend_cont != 3)
+          Don't overwrite resend for open/close condition. */
+       if ((reset_port + 1) > p_priv->resend_cont)
                p_priv->resend_cont = reset_port + 1;
        if (this_urb->status == -EINPROGRESS) {
                /*  dbg ("%s - already writing", __FUNCTION__); */
@@ -1836,8 +2028,8 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
        }
 
        /* Save reset port val for resend.
-          Don't overwrite resend for close condition. */
-       if (p_priv->resend_cont != 3)
+          Don't overwrite resend for open/close condition. */
+       if ((reset_port + 1) > p_priv->resend_cont)
                p_priv->resend_cont = reset_port + 1;
        if (this_urb->status == -EINPROGRESS) {
                dbg ("%s already writing", __FUNCTION__);
@@ -1940,11 +2132,11 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
                                    struct usb_serial_port *port,
                                    int reset_port)
 {
-       struct keyspan_usa49_portControlMessage msg;            
+       struct keyspan_usa49_portControlMessage msg;
+       struct usb_ctrlrequest                  *dr = NULL;
        struct keyspan_serial_private           *s_priv;
        struct keyspan_port_private             *p_priv;
        const struct keyspan_device_details     *d_details;
-       int                                     glocont_urb;
        struct urb                              *this_urb;
        int                                     err, device_port;
 
@@ -1954,10 +2146,9 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
        p_priv = usb_get_serial_port_data(port);
        d_details = s_priv->device_details;
 
-       glocont_urb = d_details->glocont_endpoint;
        this_urb = s_priv->glocont_urb;
 
-               /* Work out which port within the device is being setup */
+       /* Work out which port within the device is being setup */
        device_port = port->number - port->serial->minor;
 
        dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
@@ -1969,9 +2160,10 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
        }
 
        /* Save reset port val for resend.
-          Don't overwrite resend for close condition. */
-       if (p_priv->resend_cont != 3)
+          Don't overwrite resend for open/close condition. */
+       if ((reset_port + 1) > p_priv->resend_cont)
                p_priv->resend_cont = reset_port + 1;
+
        if (this_urb->status == -EINPROGRESS) {
                /*  dbg ("%s - already writing", __FUNCTION__); */
                mdelay(5);
@@ -2083,20 +2275,39 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
        msg.dtr = p_priv->dtr_state;
                
        p_priv->resend_cont = 0;
-       memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
+
+       /* if the device is a 49wg, we send control message on usb control EP 0 */
+
+       if (d_details->product_id == keyspan_usa49wg_product_id) {
+               dr = (void *)(s_priv->ctrl_buf);
+               dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
+               dr->bRequest = 0xB0;    /* 49wg control message */;
+               dr->wValue = 0;
+               dr->wIndex = 0;
+               dr->wLength = cpu_to_le16(sizeof(msg));
+
+               memcpy (s_priv->glocont_buf, &msg, sizeof(msg));
+
+               usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                            (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg),
+                            usa49_glocont_callback, serial);
+
+       } else {
+               memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
        
-       /* send the data out the device on control endpoint */
-       this_urb->transfer_buffer_length = sizeof(msg);
+               /* send the data out the device on control endpoint */
+               this_urb->transfer_buffer_length = sizeof(msg);
 
-       this_urb->dev = serial->dev;
+               this_urb->dev = serial->dev;
+       }
        if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
                dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
        }
 #if 0
        else {
                dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__,
-                   outcont_urb, this_urb->transfer_buffer_length,
-                   usb_pipeendpoint(this_urb->pipe));
+                          outcont_urb, this_urb->transfer_buffer_length,
+                          usb_pipeendpoint(this_urb->pipe));
        }
 #endif
 
@@ -2241,6 +2452,154 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
        return (0);
 }
 
+static int keyspan_usa67_send_setup(struct usb_serial *serial,
+                                   struct usb_serial_port *port,
+                                   int reset_port)
+{
+       struct keyspan_usa67_portControlMessage msg;
+       struct keyspan_serial_private           *s_priv;
+       struct keyspan_port_private             *p_priv;
+       const struct keyspan_device_details     *d_details;
+       struct urb                              *this_urb;
+       int                                     err, device_port;
+
+       dbg ("%s", __FUNCTION__);
+
+       s_priv = usb_get_serial_data(serial);
+       p_priv = usb_get_serial_port_data(port);
+       d_details = s_priv->device_details;
+
+       this_urb = s_priv->glocont_urb;
+
+       /* Work out which port within the device is being setup */
+       device_port = port->number - port->serial->minor;
+
+       /* Make sure we have an urb then send the message */
+       if (this_urb == NULL) {
+               dbg("%s - oops no urb for port %d.", __FUNCTION__,
+                       port->number);
+               return -1;
+       }
+
+       /* Save reset port val for resend.
+          Don't overwrite resend for open/close condition. */
+       if ((reset_port + 1) > p_priv->resend_cont)
+               p_priv->resend_cont = reset_port + 1;
+       if (this_urb->status == -EINPROGRESS) {
+               /*  dbg ("%s - already writing", __FUNCTION__); */
+               mdelay(5);
+               return(-1);
+       }
+
+       memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
+
+       msg.port = device_port;
+
+       /* Only set baud rate if it's changed */
+       if (p_priv->old_baud != p_priv->baud) {
+               p_priv->old_baud = p_priv->baud;
+               msg.setClocking = 0xff;
+               if (d_details->calculate_baud_rate
+                   (p_priv->baud, d_details->baudclk, &msg.baudHi,
+                    &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
+                       dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
+                           p_priv->baud);
+                       msg.baudLo = 0;
+                       msg.baudHi = 125;       /* Values for 9600 baud */
+                       msg.prescaler = 10;
+               }
+               msg.setPrescaler = 0xff;
+       }
+
+       msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
+       switch (p_priv->cflag & CSIZE) {
+       case CS5:
+               msg.lcr |= USA_DATABITS_5;
+               break;
+       case CS6:
+               msg.lcr |= USA_DATABITS_6;
+               break;
+       case CS7:
+               msg.lcr |= USA_DATABITS_7;
+               break;
+       case CS8:
+               msg.lcr |= USA_DATABITS_8;
+               break;
+       }
+       if (p_priv->cflag & PARENB) {
+               /* note USA_PARITY_NONE == 0 */
+               msg.lcr |= (p_priv->cflag & PARODD)?
+                       USA_PARITY_ODD: USA_PARITY_EVEN;
+       }
+       msg.setLcr = 0xff;
+
+       msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
+       msg.xonFlowControl = 0;
+       msg.setFlowControl = 0xff;
+       msg.forwardingLength = 16;
+       msg.xonChar = 17;
+       msg.xoffChar = 19;
+
+       if (reset_port == 1) {
+               /* Opening port */
+               msg._txOn = 1;
+               msg._txOff = 0;
+               msg.txFlush = 0;
+               msg.txBreak = 0;
+               msg.rxOn = 1;
+               msg.rxOff = 0;
+               msg.rxFlush = 1;
+               msg.rxForward = 0;
+               msg.returnStatus = 0;
+               msg.resetDataToggle = 0xff;
+       } else if (reset_port == 2) {
+               /* Closing port */
+               msg._txOn = 0;
+               msg._txOff = 1;
+               msg.txFlush = 0;
+               msg.txBreak = 0;
+               msg.rxOn = 0;
+               msg.rxOff = 1;
+               msg.rxFlush = 1;
+               msg.rxForward = 0;
+               msg.returnStatus = 0;
+               msg.resetDataToggle = 0;
+       } else {
+               /* Sending intermediate configs */
+               msg._txOn = (! p_priv->break_on);
+               msg._txOff = 0;
+               msg.txFlush = 0;
+               msg.txBreak = (p_priv->break_on);
+               msg.rxOn = 0;
+               msg.rxOff = 0;
+               msg.rxFlush = 0;
+               msg.rxForward = 0;
+               msg.returnStatus = 0;
+               msg.resetDataToggle = 0x0;
+       }
+
+       /* Do handshaking outputs */
+       msg.setTxTriState_setRts = 0xff;
+       msg.txTriState_rts = p_priv->rts_state;
+
+       msg.setHskoa_setDtr = 0xff;
+       msg.hskoa_dtr = p_priv->dtr_state;
+
+       p_priv->resend_cont = 0;
+
+       memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
+
+       /* send the data out the device on control endpoint */
+       this_urb->transfer_buffer_length = sizeof(msg);
+       this_urb->dev = serial->dev;
+
+       err = usb_submit_urb(this_urb, GFP_ATOMIC);
+       if (err != 0)
+               dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__,
+                               err);
+       return (0);
+}
+
 static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
 {
        struct usb_serial *serial = port->serial;
@@ -2265,6 +2624,9 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
        case msg_usa90:
                keyspan_usa90_send_setup(serial, port, reset_port);
                break;
+       case msg_usa67:
+               keyspan_usa67_send_setup(serial, port, reset_port);
+               break;
        }
 }
 
@@ -2313,9 +2675,19 @@ static int keyspan_startup (struct usb_serial *serial)
 
        keyspan_setup_urbs(serial);
 
-       s_priv->instat_urb->dev = serial->dev;
-       if ((err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL)) != 0) {
-               dbg("%s - submit instat urb failed %d", __FUNCTION__, err);
+       if (s_priv->instat_urb != NULL) {
+               s_priv->instat_urb->dev = serial->dev;
+               err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
+               if (err != 0)
+                       dbg("%s - submit instat urb failed %d", __FUNCTION__,
+                               err);
+       }
+       if (s_priv->indat_urb != NULL) {
+               s_priv->indat_urb->dev = serial->dev;
+               err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
+               if (err != 0)
+                       dbg("%s - submit indat urb failed %d", __FUNCTION__,
+                               err);
        }
                        
        return (0);
@@ -2335,6 +2707,7 @@ static void keyspan_shutdown (struct usb_serial *serial)
        /* Stop reading/writing urbs */
        stop_urb(s_priv->instat_urb);
        stop_urb(s_priv->glocont_urb);
+       stop_urb(s_priv->indat_urb);
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
                p_priv = usb_get_serial_port_data(port);
@@ -2348,6 +2721,7 @@ static void keyspan_shutdown (struct usb_serial *serial)
 
        /* Now free them */
        usb_free_urb(s_priv->instat_urb);
+       usb_free_urb(s_priv->indat_urb);
        usb_free_urb(s_priv->glocont_urb);
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
index c6830cbdc6df32740b43901090a826f361a06aae..8a0d17401529986b077da08a15a292d1e2de14af 100644 (file)
@@ -99,6 +99,10 @@ static int  keyspan_usa90_send_setup (struct usb_serial *serial,
                                         struct usb_serial_port *port,
                                         int reset_port);
 
+static int  keyspan_usa67_send_setup   (struct usb_serial *serial,
+                                        struct usb_serial_port *port,
+                                        int reset_port);
+
 /* Struct used for firmware - increased size of data section
    to allow Keyspan's 'C' firmware struct to be used unmodified */
 struct ezusb_hex_record {
@@ -229,15 +233,17 @@ struct ezusb_hex_record {
 #define        keyspan_usa28_product_id                0x010f
 #define        keyspan_usa28x_product_id               0x0110
 #define        keyspan_usa28xa_product_id              0x0115
+#define        keyspan_usa28xb_product_id              0x0110
+#define        keyspan_usa28xg_product_id              0x0135
 #define        keyspan_usa49w_product_id               0x010a
 #define        keyspan_usa49wlc_product_id             0x012a
-
+#define        keyspan_usa49wg_product_id              0x0131
 
 struct keyspan_device_details {
        /* product ID value */
        int     product_id;
 
-       enum    {msg_usa26, msg_usa28, msg_usa49, msg_usa90} msg_format;
+       enum    {msg_usa26, msg_usa28, msg_usa49, msg_usa90, msg_usa67} msg_format;
 
                /* Number of physical ports */
        int     num_ports;
@@ -264,6 +270,9 @@ struct keyspan_device_details {
                /* Endpoint used for input status */
        int     instat_endpoint;
 
+               /* Endpoint used for input data 49WG only */
+       int     indat_endpoint;
+
                /* Endpoint used for global control functions */
        int     glocont_endpoint;
 
@@ -287,6 +296,7 @@ static const struct keyspan_device_details usa18x_device_details = {
        .inack_endpoints        = {0x85},
        .outcont_endpoints      = {0x05},
        .instat_endpoint        = 0x87,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = 0x07,
        .calculate_baud_rate    = keyspan_usa19w_calc_baud,
        .baudclk                = KEYSPAN_USA18X_BAUDCLK,
@@ -303,6 +313,7 @@ static const struct keyspan_device_details usa19_device_details = {
        .inack_endpoints        = {0x83},
        .outcont_endpoints      = {0x03},
        .instat_endpoint        = 0x84,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = -1,
        .calculate_baud_rate    = keyspan_usa19_calc_baud,
        .baudclk                = KEYSPAN_USA19_BAUDCLK,
@@ -319,6 +330,7 @@ static const struct keyspan_device_details usa19qi_device_details = {
        .inack_endpoints        = {0x83},
        .outcont_endpoints      = {0x03},
        .instat_endpoint        = 0x84,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = -1,
        .calculate_baud_rate    = keyspan_usa28_calc_baud,
        .baudclk                = KEYSPAN_USA19_BAUDCLK,
@@ -335,6 +347,7 @@ static const struct keyspan_device_details mpr_device_details = {
        .inack_endpoints        = {0x83},
        .outcont_endpoints      = {0x03},
        .instat_endpoint        = 0x84,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = -1,
        .calculate_baud_rate    = keyspan_usa28_calc_baud,
        .baudclk                = KEYSPAN_USA19_BAUDCLK,
@@ -351,6 +364,7 @@ static const struct keyspan_device_details usa19qw_device_details = {
        .inack_endpoints        = {0x85},
        .outcont_endpoints      = {0x05},
        .instat_endpoint        = 0x87,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = 0x07,
        .calculate_baud_rate    = keyspan_usa19w_calc_baud,
        .baudclk                = KEYSPAN_USA19W_BAUDCLK,
@@ -367,6 +381,7 @@ static const struct keyspan_device_details usa19w_device_details = {
        .inack_endpoints        = {0x85},
        .outcont_endpoints      = {0x05},
        .instat_endpoint        = 0x87,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = 0x07,
        .calculate_baud_rate    = keyspan_usa19w_calc_baud,
        .baudclk                = KEYSPAN_USA19W_BAUDCLK,
@@ -383,6 +398,7 @@ static const struct keyspan_device_details usa19hs_device_details = {
        .inack_endpoints        = {-1},
        .outcont_endpoints      = {0x02},
        .instat_endpoint        = 0x82,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = -1,
        .calculate_baud_rate    = keyspan_usa19hs_calc_baud,
        .baudclk                = KEYSPAN_USA19HS_BAUDCLK,
@@ -399,6 +415,7 @@ static const struct keyspan_device_details usa28_device_details = {
        .inack_endpoints        = {0x85, 0x86},
        .outcont_endpoints      = {0x05, 0x06},
        .instat_endpoint        = 0x87,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = 0x07,
        .calculate_baud_rate    = keyspan_usa28_calc_baud,
        .baudclk                = KEYSPAN_USA28_BAUDCLK,                
@@ -415,6 +432,7 @@ static const struct keyspan_device_details usa28x_device_details = {
        .inack_endpoints        = {0x85, 0x86},
        .outcont_endpoints      = {0x05, 0x06},
        .instat_endpoint        = 0x87,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = 0x07,
        .calculate_baud_rate    = keyspan_usa19w_calc_baud,
        .baudclk                = KEYSPAN_USA28X_BAUDCLK,
@@ -431,11 +449,28 @@ static const struct keyspan_device_details usa28xa_device_details = {
        .inack_endpoints        = {0x85, 0x86},
        .outcont_endpoints      = {0x05, 0x06},
        .instat_endpoint        = 0x87,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = 0x07,
        .calculate_baud_rate    = keyspan_usa19w_calc_baud,
        .baudclk                = KEYSPAN_USA28X_BAUDCLK,
 };
 
+static const struct keyspan_device_details usa28xg_device_details = {
+       .product_id             = keyspan_usa28xg_product_id,
+       .msg_format             = msg_usa67,
+       .num_ports              = 2,
+       .indat_endp_flip        = 0,
+       .outdat_endp_flip       = 0,
+       .indat_endpoints        = {0x84, 0x88},
+       .outdat_endpoints       = {0x02, 0x06},
+       .inack_endpoints        = {-1, -1},
+       .outcont_endpoints      = {-1, -1},
+       .instat_endpoint        = 0x81,
+       .indat_endpoint         = -1,
+       .glocont_endpoint       = 0x01,
+       .calculate_baud_rate    = keyspan_usa19w_calc_baud,
+       .baudclk                = KEYSPAN_USA28X_BAUDCLK,
+};
 /* We don't need a separate entry for the usa28xb as it appears as a 28x anyway */
 
 static const struct keyspan_device_details usa49w_device_details = {
@@ -449,6 +484,7 @@ static const struct keyspan_device_details usa49w_device_details = {
        .inack_endpoints        = {-1, -1, -1, -1},
        .outcont_endpoints      = {-1, -1, -1, -1},
        .instat_endpoint        = 0x87,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = 0x07,
        .calculate_baud_rate    = keyspan_usa19w_calc_baud,
        .baudclk                = KEYSPAN_USA49W_BAUDCLK,
@@ -465,11 +501,29 @@ static const struct keyspan_device_details usa49wlc_device_details = {
        .inack_endpoints        = {-1, -1, -1, -1},
        .outcont_endpoints      = {-1, -1, -1, -1},
        .instat_endpoint        = 0x87,
+       .indat_endpoint         = -1,
        .glocont_endpoint       = 0x07,
        .calculate_baud_rate    = keyspan_usa19w_calc_baud,
        .baudclk                = KEYSPAN_USA19W_BAUDCLK,
 };
 
+static const struct keyspan_device_details usa49wg_device_details = {
+       .product_id             = keyspan_usa49wg_product_id,
+       .msg_format             = msg_usa49,
+       .num_ports              = 4,
+       .indat_endp_flip        = 0,
+       .outdat_endp_flip       = 0,
+       .indat_endpoints        = {-1, -1, -1, -1},             /* single 'global' data in EP */
+       .outdat_endpoints       = {0x01, 0x02, 0x04, 0x06},
+       .inack_endpoints        = {-1, -1, -1, -1},
+       .outcont_endpoints      = {-1, -1, -1, -1},
+       .instat_endpoint        = 0x81,
+       .indat_endpoint         = 0x88,
+       .glocont_endpoint       = 0x00,                         /* uses control EP */
+       .calculate_baud_rate    = keyspan_usa19w_calc_baud,
+       .baudclk                = KEYSPAN_USA19W_BAUDCLK,
+};
+
 static const struct keyspan_device_details *keyspan_devices[] = {
        &usa18x_device_details,
        &usa19_device_details,
@@ -481,9 +535,11 @@ static const struct keyspan_device_details *keyspan_devices[] = {
        &usa28_device_details,
        &usa28x_device_details,
        &usa28xa_device_details,
+       &usa28xg_device_details,
        /* 28xb not required as it renumerates as a 28x */
        &usa49w_device_details,
        &usa49wlc_device_details,
+       &usa49wg_device_details,
        NULL,
 };
 
@@ -510,8 +566,11 @@ static struct usb_device_id keyspan_ids_combined[] = {
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
+       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
+       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)},
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
+       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
        { } /* Terminating entry */
 };
 
@@ -557,12 +616,15 @@ static struct usb_device_id keyspan_2port_ids[] = {
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
+       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
+       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
        { } /* Terminating entry */
 };
 
 static struct usb_device_id keyspan_4port_ids[] = {
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) },
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
+       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
        { } /* Terminating entry */
 };
 
@@ -573,7 +635,6 @@ static struct usb_serial_driver keyspan_pre_device = {
                .name           = "keyspan_no_firm",
        },
        .description            = "Keyspan - (without firmware)",
-       .usb_driver             = &keyspan_driver,
        .id_table               = keyspan_pre_ids,
        .num_interrupt_in       = NUM_DONT_CARE,
        .num_bulk_in            = NUM_DONT_CARE,
@@ -588,7 +649,6 @@ static struct usb_serial_driver keyspan_1port_device = {
                .name           = "keyspan_1",
        },
        .description            = "Keyspan 1 port adapter",
-       .usb_driver             = &keyspan_driver,
        .id_table               = keyspan_1port_ids,
        .num_interrupt_in       = NUM_DONT_CARE,
        .num_bulk_in            = NUM_DONT_CARE,
@@ -616,7 +676,6 @@ static struct usb_serial_driver keyspan_2port_device = {
                .name           = "keyspan_2",
        },
        .description            = "Keyspan 2 port adapter",
-       .usb_driver             = &keyspan_driver,
        .id_table               = keyspan_2port_ids,
        .num_interrupt_in       = NUM_DONT_CARE,
        .num_bulk_in            = NUM_DONT_CARE,
@@ -644,11 +703,10 @@ static struct usb_serial_driver keyspan_4port_device = {
                .name           = "keyspan_4",
        },
        .description            = "Keyspan 4 port adapter",
-       .usb_driver             = &keyspan_driver,
        .id_table               = keyspan_4port_ids,
        .num_interrupt_in       = NUM_DONT_CARE,
-       .num_bulk_in            = 5,
-       .num_bulk_out           = 5,
+       .num_bulk_in            = NUM_DONT_CARE,
+       .num_bulk_out           = NUM_DONT_CARE,
        .num_ports              = 4,
        .open                   = keyspan_open,
        .close                  = keyspan_close,
index dd0b66a6ed5d00825a93c571d867f31abd61a183..be9ac20a8f10b3adeb456192f84246da79206419 100644 (file)
@@ -218,11 +218,12 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
                struct tty_struct *tty = port->tty;
        unsigned char *data = urb->transfer_buffer;
        int i;
-       int status;
+       int retval;
+       int status = urb->status;
        struct keyspan_pda_private *priv;
        priv = usb_get_serial_port_data(port);
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -230,10 +231,12 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d",
+                   __FUNCTION__, status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d",
+                   __FUNCTION__, status);
                goto exit;
        }
 
@@ -268,10 +271,10 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
        }
 
 exit:
-       status = usb_submit_urb (urb, GFP_ATOMIC);
-       if (status)
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, status);
+                    __FUNCTION__, retval);
 }
 
 
diff --git a/drivers/usb/serial/keyspan_usa67msg.h b/drivers/usb/serial/keyspan_usa67msg.h
new file mode 100644 (file)
index 0000000..20fa3e2
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+       usa67msg.h
+
+       Copyright (c) 1998-2007 InnoSys Incorporated.  All Rights Reserved
+       This file is available under a BSD-style copyright
+
+       Keyspan USB Async Firmware to run on Anchor FX1
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+
+       1. Redistributions of source code must retain this licence text
+       without modification, this list of conditions, and the following
+       disclaimer.  The following copyright notice must appear immediately at
+       the beginning of all source files:
+
+               Copyright (c) 1998-2007 InnoSys Incorporated.  All Rights Reserved
+
+               This file is available under a BSD-style copyright
+
+       2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+       3. The name of InnoSys Incorprated may not be used to endorse or promote
+       products derived from this software without specific prior written
+       permission.
+
+       THIS SOFTWARE IS PROVIDED BY INNOSYS CORP. ``AS IS'' AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+       NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+       INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+       (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+       SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+       CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+       LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+       OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+       SUCH DAMAGE.
+
+       Fourth revision: This message format supports the USA28XG
+
+       Buffer formats for RX/TX data messages are not defined by
+       a structure, but are described here:
+
+       USB OUT (host -> USAxx, transmit) messages contain a
+       REQUEST_ACK indicator (set to 0xff to request an ACK at the
+       completion of transmit; 0x00 otherwise), followed by data:
+
+               RQSTACK DAT DAT DAT ...
+
+       with a total data length of up to 63.
+
+       USB IN (USAxx -> host, receive) messages begin with a status
+       byte in which the 0x80 bit is either:
+
+               (a)     0x80 bit clear
+                       indicates that the bytes following it are all data
+                       bytes:
+
+                               STAT DATA DATA DATA DATA DATA ...
+
+                       for a total of up to 63 DATA bytes,
+
+       or:
+
+               (b)     0x80 bit set
+                       indiates that the bytes following alternate data and
+                       status bytes:
+
+                               STAT DATA STAT DATA STAT DATA STAT DATA ...
+
+                       for a total of up to 32 DATA bytes.
+
+       The valid bits in the STAT bytes are:
+
+               OVERRUN 0x02
+               PARITY  0x04
+               FRAMING 0x08
+               BREAK   0x10
+
+       Notes:
+
+       (1) The OVERRUN bit can appear in either (a) or (b) format
+               messages, but the but the PARITY/FRAMING/BREAK bits
+               only appear in (b) format messages.
+       (2) For the host to determine the exact point at which the
+               overrun occurred (to identify the point in the data
+               stream at which the data was lost), it needs to count
+               128 characters, starting at the first character of the
+               message in which OVERRUN was reported; the lost character(s)
+               would have been received between the 128th and 129th
+               characters.
+       (3)     An RX data message in which the first byte has 0x80 clear
+               serves as a "break off" indicator.
+
+       revision history:
+
+       1999feb10       add reportHskiaChanges to allow us to ignore them
+       1999feb10       add txAckThreshold for fast+loose throughput enhancement
+       1999mar30       beef up support for RX error reporting
+       1999apr14       add resetDataToggle to control message
+       2000jan04       merge with usa17msg.h
+       2000jun01       add extended BSD-style copyright text
+       2001jul05       change message format to improve OVERRUN case
+       2002jun05       update copyright date, improve comments
+       2006feb06       modify for FX1 chip
+
+*/
+
+#ifndef        __USA67MSG__
+#define        __USA67MSG__
+
+
+// all things called "ControlMessage" are sent on the 'control' endpoint
+
+typedef struct keyspan_usa67_portControlMessage
+{
+       u8      port;           // 0 or 1 (selects port)
+       /*
+               there are three types of "commands" sent in the control message:
+
+               1.      configuration changes which must be requested by setting
+                       the corresponding "set" flag (and should only be requested
+                       when necessary, to reduce overhead on the device):
+       */
+       u8      setClocking,    // host requests baud rate be set
+               baudLo,                 // host does baud divisor calculation
+               baudHi,                 // baudHi is only used for first port (gives lower rates)
+               externalClock_txClocking,
+                                               // 0=internal, other=external
+
+               setLcr,                 // host requests lcr be set
+               lcr,                    // use PARITY, STOPBITS, DATABITS below
+
+               setFlowControl, // host requests flow control be set
+               ctsFlowControl, // 1=use CTS flow control, 0=don't
+               xonFlowControl, // 1=use XON/XOFF flow control, 0=don't
+               xonChar,                // specified in current character format
+               xoffChar,               // specified in current character format
+
+               setTxTriState_setRts,
+                                               // host requests TX tri-state be set
+               txTriState_rts, // 1=active (normal), 0=tristate (off)
+
+               setHskoa_setDtr,
+                                               // host requests HSKOA output be set
+               hskoa_dtr,              // 1=on, 0=off
+
+               setPrescaler,   // host requests prescalar be set (default: 13)
+               prescaler;              // specified as N/8; values 8-ff are valid
+                                               // must be set any time internal baud rate is set;
+                                               // must not be set when external clocking is used
+
+       /*
+               3.      configuration data which is simply used as is (no overhead,
+                       but must be specified correctly in every host message).
+       */
+       u8      forwardingLength,  // forward when this number of chars available
+               reportHskiaChanges_dsrFlowControl,
+                                               // 1=normal; 0=ignore external clock
+                                               // 1=use DSR flow control, 0=don't
+               txAckThreshold, // 0=not allowed, 1=normal, 2-255 deliver ACK faster
+               loopbackMode;   // 0=no loopback, 1=loopback enabled
+
+       /*
+               4.      commands which are flags only; these are processed in order
+                       (so that, e.g., if both _txOn and _txOff flags are set, the
+                       port ends in a TX_OFF state); any non-zero value is respected
+       */
+       u8      _txOn,                  // enable transmitting (and continue if there's data)
+               _txOff,                 // stop transmitting
+               txFlush,                // toss outbound data
+               txBreak,                // turn on break (cleared by _txOn)
+               rxOn,                   // turn on receiver
+               rxOff,                  // turn off receiver
+               rxFlush,                // toss inbound data
+               rxForward,              // forward all inbound data, NOW (as if fwdLen==1)
+               returnStatus,   // return current status (even if it hasn't changed)
+               resetDataToggle;// reset data toggle state to DATA0
+
+} keyspan_usa67_portControlMessage;
+
+// defines for bits in lcr
+#define        USA_DATABITS_5          0x00
+#define        USA_DATABITS_6          0x01
+#define        USA_DATABITS_7          0x02
+#define        USA_DATABITS_8          0x03
+#define        STOPBITS_5678_1         0x00    // 1 stop bit for all byte sizes
+#define        STOPBITS_5_1p5          0x04    // 1.5 stop bits for 5-bit byte
+#define        STOPBITS_678_2          0x04    // 2 stop bits for 6/7/8-bit byte
+#define        USA_PARITY_NONE         0x00
+#define        USA_PARITY_ODD          0x08
+#define        USA_PARITY_EVEN         0x18
+#define        PARITY_1                        0x28
+#define        PARITY_0                        0x38
+
+// all things called "StatusMessage" are sent on the status endpoint
+
+typedef struct keyspan_usa67_portStatusMessage // one for each port
+{
+       u8      port,                   // 0=first, 1=second, other=see below
+               hskia_cts,              // reports HSKIA pin
+               gpia_dcd,               // reports GPIA pin
+               _txOff,                 // port has been disabled (by host)
+               _txXoff,                // port is in XOFF state (either host or RX XOFF)
+               txAck,                  // indicates a TX message acknowledgement
+               rxEnabled,              // as configured by rxOn/rxOff 1=on, 0=off
+               controlResponse;// 1=a control message has been processed
+} keyspan_usa67_portStatusMessage;
+
+// bits in RX data message when STAT byte is included
+#define        RXERROR_OVERRUN 0x02
+#define        RXERROR_PARITY  0x04
+#define        RXERROR_FRAMING 0x08
+#define        RXERROR_BREAK   0x10
+
+typedef struct keyspan_usa67_globalControlMessage
+{
+       u8      port,                           // 3
+               sendGlobalStatus,       // 2=request for two status responses
+               resetStatusToggle,      // 1=reset global status toggle
+               resetStatusCount;       // a cycling value
+} keyspan_usa67_globalControlMessage;
+
+typedef struct keyspan_usa67_globalStatusMessage
+{
+       u8      port,                           // 3
+               sendGlobalStatus,       // from request, decremented
+               resetStatusCount;       // as in request
+} keyspan_usa67_globalStatusMessage;
+
+typedef struct keyspan_usa67_globalDebugMessage
+{
+       u8      port,                           // 2
+               a,
+               b,
+               c,
+               d;
+} keyspan_usa67_globalDebugMessage;
+
+// ie: the maximum length of an FX1 endpoint buffer
+#define        MAX_DATA_LEN                    64
+
+// update status approx. 60 times a second (16.6666 ms)
+#define        STATUS_UPDATE_INTERVAL  16
+
+// status rationing tuning value (each port gets checked each n ms)
+#define        STATUS_RATION   10
+
+#endif
+
+
index 7b085f334cebe2de693b21a58a67a6f809d8f52a..5a4127e62c4ad4f08089eafd3fa4d4e131cd578d 100644 (file)
@@ -567,12 +567,13 @@ exit:
 static void klsi_105_write_bulk_callback ( struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
-       
-       if (urb->status) {
+
+       if (status) {
                dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
-                   urb->status);
+                   status);
                return;
        }
 
@@ -631,16 +632,17 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
        int rc;
+       int status = urb->status;
 
-        dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __FUNCTION__, port->number);
 
        /* The urb might have been killed. */
-        if (urb->status) {
-                dbg("%s - nonzero read bulk status received: %d", __FUNCTION__,
-                   urb->status);
-                return;
-        }
-       
+       if (status) {
+               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__,
+                   status);
+               return;
+       }
+
        /* The data received is again preceded by a length double-byte in LSB-
         * first order (see klsi_105_write() )
         */
index 0683b51f0932f15a783d4d96dfb53fd3edef75cd..02a86dbc0e9759673000eeb4521a8d0bafabc5ed 100644 (file)
@@ -358,24 +358,26 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp)
 }
 
 
-static void kobil_read_int_callback( struct urb *purb)
+static void kobil_read_int_callback(struct urb *urb)
 {
        int result;
-       struct usb_serial_port *port = (struct usb_serial_port *) purb->context;
+       struct usb_serial_port *port = urb->context;
        struct tty_struct *tty;
-       unsigned char *data = purb->transfer_buffer;
+       unsigned char *data = urb->transfer_buffer;
+       int status = urb->status;
 //     char *dbg_data;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (purb->status) {
-               dbg("%s - port %d Read int status not zero: %d", __FUNCTION__, port->number, purb->status);
+       if (status) {
+               dbg("%s - port %d Read int status not zero: %d",
+                   __FUNCTION__, port->number, status);
                return;
        }
-       
-       tty = port->tty; 
-       if (purb->actual_length) {
-               
+
+       tty = port->tty;
+       if (urb->actual_length) {
+
                // BEGIN DEBUG
                /*
                  dbg_data = kzalloc((3 *  purb->actual_length + 10) * sizeof(char), GFP_KERNEL);
@@ -390,15 +392,15 @@ static void kobil_read_int_callback( struct urb *purb)
                */
                // END DEBUG
 
-               tty_buffer_request_room(tty, purb->actual_length);
-               tty_insert_flip_string(tty, data, purb->actual_length);
+               tty_buffer_request_room(tty, urb->actual_length);
+               tty_insert_flip_string(tty, data, urb->actual_length);
                tty_flip_buffer_push(tty);
        }
 
        // someone sets the dev to 0 if the close method has been called
        port->interrupt_in_urb->dev = port->serial->dev;
 
-       result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC ); 
+       result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
        dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
 }
 
index 3db1adc25f842d30934b9b07c6cfd626f55a12fa..2a3fabcf5186aa2179b88f4cc64acaa90fba1411 100644 (file)
@@ -81,7 +81,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "z2.0"          /* Linux in-kernel version */
+#define DRIVER_VERSION "z2.1"          /* Linux in-kernel version */
 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
 
@@ -110,6 +110,10 @@ static int  mct_u232_tiocmget               (struct usb_serial_port *port,
 static int  mct_u232_tiocmset           (struct usb_serial_port *port,
                                          struct file *file, unsigned int set,
                                          unsigned int clear);
+static void mct_u232_throttle           (struct usb_serial_port *port);
+static void mct_u232_unthrottle                 (struct usb_serial_port *port);
+
+
 /*
  * All of the device info needed for the MCT USB-RS232 converter.
  */
@@ -145,6 +149,8 @@ static struct usb_serial_driver mct_u232_device = {
        .num_ports =         1,
        .open =              mct_u232_open,
        .close =             mct_u232_close,
+       .throttle =          mct_u232_throttle,
+       .unthrottle =        mct_u232_unthrottle,
        .read_int_callback = mct_u232_read_int_callback,
        .ioctl =             mct_u232_ioctl,
        .set_termios =       mct_u232_set_termios,
@@ -162,8 +168,11 @@ struct mct_u232_private {
        unsigned char        last_lcr;      /* Line Control Register */
        unsigned char        last_lsr;      /* Line Status Register */
        unsigned char        last_msr;      /* Modem Status Register */
+       unsigned int         rx_flags;      /* Throttling flags */
 };
 
+#define THROTTLED              0x01
+
 /*
  * Handle vendor specific USB requests
  */
@@ -216,11 +225,13 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value)
        }
 }
 
-static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
+static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port,
+                                 int value)
 {
        __le32 divisor;
         int rc;
         unsigned char zero_byte = 0;
+        unsigned char cts_enable_byte = 0;
 
        divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
 
@@ -238,10 +249,17 @@ static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
           'baud rate change' message.  The actual functionality of the
           request codes in these messages is not fully understood but these
           particular codes are never seen in any operation besides a baud
-          rate change.  Both of these messages send a single byte of data
-          whose value is always zero.  The second of these two extra messages
-          is required in order for data to be properly written to an RS-232
-          device which does not assert the 'CTS' signal. */
+          rate change.  Both of these messages send a single byte of data.
+          In the first message, the value of this byte is always zero.
+
+          The second message has been determined experimentally to control
+          whether data will be transmitted to a device which is not asserting
+          the 'CTS' signal.  If the second message's data byte is zero, data
+          will be transmitted even if 'CTS' is not asserted (i.e. no hardware
+          flow control).  if the second message's data byte is nonzero (a value
+          of 1 is used by this driver), data will not be transmitted to a device
+          which is not asserting 'CTS'.
+       */
 
        rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                             MCT_U232_SET_UNKNOWN1_REQUEST, 
@@ -252,14 +270,19 @@ static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
                err("Sending USB device request code %d failed (error = %d)", 
                    MCT_U232_SET_UNKNOWN1_REQUEST, rc);
 
+       if (port && C_CRTSCTS(port->tty)) {
+          cts_enable_byte = 1;
+       }
+
+        dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte);
        rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                            MCT_U232_SET_UNKNOWN2_REQUEST, 
+                            MCT_U232_SET_CTS_REQUEST,
                             MCT_U232_SET_REQUEST_TYPE,
-                            0, 0, &zero_byte, MCT_U232_SET_UNKNOWN2_SIZE, 
+                            0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
                             WDR_TIMEOUT);
        if (rc < 0)
-               err("Sending USB device request code %d failed (error = %d)", 
-                   MCT_U232_SET_UNKNOWN2_REQUEST, rc);
+         err("Sending USB device request code %d failed (error = %d)",
+             MCT_U232_SET_CTS_REQUEST, rc);
 
         return rc;
 } /* mct_u232_set_baud_rate */
@@ -458,8 +481,25 @@ error:
 
 static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
 {
+       unsigned int c_cflag;
+       unsigned long flags;
+       unsigned int control_state;
+       struct mct_u232_private *priv = usb_get_serial_port_data(port);
        dbg("%s port %d", __FUNCTION__, port->number);
 
+       if (port->tty) {
+               c_cflag = port->tty->termios->c_cflag;
+               if (c_cflag & HUPCL) {
+                  /* drop DTR and RTS */
+                  spin_lock_irqsave(&priv->lock, flags);
+                  priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+                  control_state = priv->control_state;
+                  spin_unlock_irqrestore(&priv->lock, flags);
+                  mct_u232_set_modem_ctrl(port->serial, control_state);
+               }
+       }
+
+
        if (port->serial->dev) {
                /* shutdown our urbs */
                usb_kill_urb(port->write_urb);
@@ -476,10 +516,11 @@ static void mct_u232_read_int_callback (struct urb *urb)
        struct usb_serial *serial = port->serial;
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
-       int status;
+       int retval;
+       int status = urb->status;
        unsigned long flags;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -487,10 +528,12 @@ static void mct_u232_read_int_callback (struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d",
+                   __FUNCTION__, status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d",
+                   __FUNCTION__, status);
                goto exit;
        }
 
@@ -554,10 +597,10 @@ static void mct_u232_read_int_callback (struct urb *urb)
 #endif
        spin_unlock_irqrestore(&priv->lock, flags);
 exit:
-       status = usb_submit_urb (urb, GFP_ATOMIC);
-       if (status)
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, status);
+                    __FUNCTION__, retval);
 } /* mct_u232_read_int_callback */
 
 static void mct_u232_set_termios (struct usb_serial_port *port,
@@ -565,11 +608,10 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
 {
        struct usb_serial *serial = port->serial;
        struct mct_u232_private *priv = usb_get_serial_port_data(port);
-       unsigned int iflag = port->tty->termios->c_iflag;
        unsigned int cflag = port->tty->termios->c_cflag;
        unsigned int old_cflag = old_termios->c_cflag;
        unsigned long flags;
-       unsigned int control_state, new_state;
+       unsigned int control_state;
        unsigned char last_lcr;
 
        /* get a local copy of the current port settings */
@@ -585,18 +627,14 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
         * Premature optimization is the root of all evil.
         */
 
-        /* reassert DTR and (maybe) RTS on transition from B0 */
+        /* reassert DTR and RTS on transition from B0 */
        if ((old_cflag & CBAUD) == B0) {
                dbg("%s: baud was B0", __FUNCTION__);
-               control_state |= TIOCM_DTR;
-               /* don't set RTS if using hardware flow control */
-               if (!(old_cflag & CRTSCTS)) {
-                       control_state |= TIOCM_RTS;
-               }
+               control_state |= TIOCM_DTR | TIOCM_RTS;
                mct_u232_set_modem_ctrl(serial, control_state);
        }
 
-       mct_u232_set_baud_rate(serial, cflag & CBAUD);
+       mct_u232_set_baud_rate(serial, port, cflag & CBAUD);
 
        if ((cflag & CBAUD) == B0 ) {
                dbg("%s: baud is B0", __FUNCTION__);
@@ -638,21 +676,6 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
 
        mct_u232_set_line_ctrl(serial, last_lcr);
 
-       /*
-        * Set flow control: well, I do not really now how to handle DTR/RTS.
-        * Just do what we have seen with SniffUSB on Win98.
-        */
-       /* Drop DTR/RTS if no flow control otherwise assert */
-       new_state = control_state;
-       if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
-               new_state |= TIOCM_DTR | TIOCM_RTS;
-       else
-               new_state &= ~(TIOCM_DTR | TIOCM_RTS);
-       if (new_state != control_state) {
-               mct_u232_set_modem_ctrl(serial, new_state);
-               control_state = new_state;
-       }
-
        /* save off the modified port settings */
        spin_lock_irqsave(&priv->lock, flags);
        priv->control_state = control_state;
@@ -747,6 +770,50 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
        return 0;
 } /* mct_u232_ioctl */
 
+static void mct_u232_throttle (struct usb_serial_port *port)
+{
+       struct mct_u232_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned int control_state;
+       struct tty_struct *tty;
+
+       tty = port->tty;
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       priv->rx_flags |= THROTTLED;
+       if (C_CRTSCTS(tty)) {
+         priv->control_state &= ~TIOCM_RTS;
+         control_state = priv->control_state;
+         spin_unlock_irqrestore(&priv->lock, flags);
+         (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+       } else {
+         spin_unlock_irqrestore(&priv->lock, flags);
+       }
+}
+
+
+static void mct_u232_unthrottle (struct usb_serial_port *port)
+{
+       struct mct_u232_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned int control_state;
+       struct tty_struct *tty;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       tty = port->tty;
+       spin_lock_irqsave(&priv->lock, flags);
+       if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
+         priv->rx_flags &= ~THROTTLED;
+         priv->control_state |= TIOCM_RTS;
+         control_state = priv->control_state;
+         spin_unlock_irqrestore(&priv->lock, flags);
+         (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+       } else {
+         spin_unlock_irqrestore(&priv->lock, flags);
+       }
+}
 
 static int __init mct_u232_init (void)
 {
index 73dd0d984cd358e8f022ce8467327a407afc208f..a61bac8f224aded9acfca8b794d385c6bcf79811 100644 (file)
 #define MCT_U232_SET_UNKNOWN1_REQUEST   11  /* Unknown functionality */
 #define MCT_U232_SET_UNKNOWN1_SIZE       1
 
-/* This USB device request code is not well understood.  It is transmitted by
-   the MCT-supplied Windows driver whenever the baud rate changes. 
+/* This USB device request code appears to control whether CTS is required
+   during transmission.
    
-   Without this USB device request, the USB/RS-232 adapter will not write to
-   RS-232 devices which do not assert the 'CTS' signal.
+   Sending a zero byte allows data transmission to a device which is not
+   asserting CTS.  Sending a '1' byte will cause transmission to be deferred
+   until the device asserts CTS.
 */
-#define MCT_U232_SET_UNKNOWN2_REQUEST   12  /* Unknown functionality */
-#define MCT_U232_SET_UNKNOWN2_SIZE       1
+#define MCT_U232_SET_CTS_REQUEST   12
+#define MCT_U232_SET_CTS_SIZE       1
 
 /*
  * Baud rate (divisor)
@@ -439,7 +440,7 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value);
  * which says "U232-P9" ;-)
  * 
  * The circuit board inside the adaptor contains a Philips PDIUSBD12
- * USB endpoint chip and a Phillips P87C52UBAA microcontroller with
+ * USB endpoint chip and a Philips P87C52UBAA microcontroller with
  * embedded UART.  Exhaustive documentation for these is available at:
  *
  *   http://www.semiconductors.philips.com/pip/p87c52ubaa
index b563e2ad8728ebe261065ec7ebc6430e7c78b8b8..231b584f6d0f22b5a5e7c27a91289f2d5619e7d6 100644 (file)
@@ -9,9 +9,9 @@
  * the Free Software Foundation, version 2 of the License.
  *
  * Developed by:
- *     VijayaKumar.G.N. <vijaykumar@aspirecom.net>
- *     AjayKumar <ajay@aspirecom.net>
- *     Gurudeva.N. <gurudev@aspirecom.net>
+ *     Vijaya Kumar <vijaykumar.gn@gmail.com>
+ *     Ajay Kumar <naanuajay@yahoo.com>
+ *     Gurudeva <ngurudeva@yahoo.com>
  *
  * Cleaned up from the original by:
  *     Greg Kroah-Hartman <gregkh@suse.de>
@@ -103,6 +103,7 @@ static void mos7720_interrupt_callback(struct urb *urb)
 {
        int result;
        int length;
+       int status = urb->status;
        __u8 *data;
        __u8 sp1;
        __u8 sp2;
@@ -114,7 +115,7 @@ static void mos7720_interrupt_callback(struct urb *urb)
                return;
        }
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -123,11 +124,11 @@ static void mos7720_interrupt_callback(struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d", __FUNCTION__,
-                   urb->status);
+                   status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d", __FUNCTION__,
-                   urb->status);
+                   status);
                goto exit;
        }
 
@@ -198,14 +199,15 @@ exit:
  */
 static void mos7720_bulk_in_callback(struct urb *urb)
 {
-       int status;
+       int retval;
        unsigned char *data ;
        struct usb_serial_port *port;
        struct moschip_port *mos7720_port;
        struct tty_struct *tty;
+       int status = urb->status;
 
-       if (urb->status) {
-               dbg("nonzero read bulk status received: %d",urb->status);
+       if (status) {
+               dbg("nonzero read bulk status received: %d", status);
                return;
        }
 
@@ -236,10 +238,10 @@ static void mos7720_bulk_in_callback(struct urb *urb)
        if (port->read_urb->status != -EINPROGRESS) {
                port->read_urb->dev = port->serial->dev;
 
-               status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-               if (status)
-                       dbg("usb_submit_urb(read bulk) failed, status = %d",
-                           status);
+               retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+               if (retval)
+                       dbg("usb_submit_urb(read bulk) failed, retval = %d",
+                           retval);
        }
 }
 
@@ -252,9 +254,10 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
 {
        struct moschip_port *mos7720_port;
        struct tty_struct *tty;
+       int status = urb->status;
 
-       if (urb->status) {
-               dbg("nonzero write bulk status received:%d", urb->status);
+       if (status) {
+               dbg("nonzero write bulk status received:%d", status);
                return;
        }
 
@@ -1235,16 +1238,6 @@ static void mos7720_set_termios(struct usb_serial_port *port,
                return;
        }
 
-       /* check that they really want us to change something */
-       if (old_termios) {
-               if ((cflag == old_termios->c_cflag) &&
-                   (RELEVANT_IFLAG(tty->termios->c_iflag) ==
-                    RELEVANT_IFLAG(old_termios->c_iflag))) {
-                       dbg("Nothing to change");
-                       return;
-               }
-       }
-
        dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
            tty->termios->c_cflag,
            RELEVANT_IFLAG(tty->termios->c_iflag));
index 36620c651079ccb4b20e8bde21e0f2df6581c226..37f41f576d3d9db9d2fee3ec412c69a0ad4441a4 100644 (file)
@@ -434,6 +434,7 @@ static void mos7840_control_callback(struct urb *urb)
        struct moschip_port *mos7840_port;
        __u8 regval = 0x0;
        int result = 0;
+       int status = urb->status;
 
        if (!urb) {
                dbg("%s", "Invalid Pointer !!!!:\n");
@@ -442,7 +443,7 @@ static void mos7840_control_callback(struct urb *urb)
 
        mos7840_port = (struct moschip_port *)urb->context;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -451,11 +452,11 @@ static void mos7840_control_callback(struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d", __FUNCTION__,
-                   urb->status);
+                   status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d", __FUNCTION__,
-                   urb->status);
+                   status);
                goto exit;
        }
 
@@ -521,6 +522,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
        __u8 sp[5], st;
        int i, rv = 0;
        __u16 wval, wreg = 0;
+       int status = urb->status;
 
        dbg("%s", " : Entering\n");
        if (!urb) {
@@ -528,7 +530,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
                return;
        }
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -537,11 +539,11 @@ static void mos7840_interrupt_callback(struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d", __FUNCTION__,
-                   urb->status);
+                   status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d", __FUNCTION__,
-                   urb->status);
+                   status);
                goto exit;
        }
 
@@ -666,20 +668,21 @@ static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port,
 
 static void mos7840_bulk_in_callback(struct urb *urb)
 {
-       int status;
+       int retval;
        unsigned char *data;
        struct usb_serial *serial;
        struct usb_serial_port *port;
        struct moschip_port *mos7840_port;
        struct tty_struct *tty;
+       int status = urb->status;
 
        if (!urb) {
                dbg("%s", "Invalid Pointer !!!!:\n");
                return;
        }
 
-       if (urb->status) {
-               dbg("nonzero read bulk status received: %d", urb->status);
+       if (status) {
+               dbg("nonzero read bulk status received: %d", status);
                return;
        }
 
@@ -729,11 +732,11 @@ static void mos7840_bulk_in_callback(struct urb *urb)
 
        mos7840_port->read_urb->dev = serial->dev;
 
-       status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+       retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
 
-       if (status) {
-               dbg(" usb_submit_urb(read bulk) failed, status = %d",
-                status);
+       if (retval) {
+               dbg(" usb_submit_urb(read bulk) failed, retval = %d",
+                retval);
        }
 }
 
@@ -747,6 +750,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
 {
        struct moschip_port *mos7840_port;
        struct tty_struct *tty;
+       int status = urb->status;
        int i;
 
        if (!urb) {
@@ -764,8 +768,8 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
        }
        spin_unlock(&mos7840_port->pool_lock);
 
-       if (urb->status) {
-               dbg("nonzero write bulk status received:%d\n", urb->status);
+       if (status) {
+               dbg("nonzero write bulk status received:%d\n", status);
                return;
        }
 
@@ -2185,16 +2189,6 @@ static void mos7840_set_termios(struct usb_serial_port *port,
                return;
        }
 
-       /* check that they really want us to change something */
-       if (old_termios) {
-               if ((cflag == old_termios->c_cflag) &&
-                   (RELEVANT_IFLAG(tty->termios->c_iflag) ==
-                    RELEVANT_IFLAG(old_termios->c_iflag))) {
-                       dbg("%s\n", "Nothing to change");
-                       return;
-               }
-       }
-
        dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
            tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
 
@@ -2253,30 +2247,6 @@ static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
        return 0;
 }
 
-/*****************************************************************************
- * mos7840_get_bytes_avail - get number of bytes available
- *
- * Purpose: Let user call ioctl to get the count of number of bytes available.
- *****************************************************************************/
-
-static int mos7840_get_bytes_avail(struct moschip_port *mos7840_port,
-                                  unsigned int __user *value)
-{
-       unsigned int result = 0;
-       struct tty_struct *tty = mos7840_port->port->tty;
-
-       if (!tty)
-               return -ENOIOCTLCMD;
-
-       result = tty->read_cnt;
-
-       dbg("%s(%d) = %d", __FUNCTION__, mos7840_port->port->number, result);
-       if (copy_to_user(value, &result, sizeof(int)))
-               return -EFAULT;
-
-       return -ENOIOCTLCMD;
-}
-
 /*****************************************************************************
  * mos7840_set_modem_info
  *      function to set modem info
@@ -2425,8 +2395,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
        struct async_icount cprev;
        struct serial_icounter_struct icount;
        int mosret = 0;
-       int retval;
-       struct tty_ldisc *ld;
 
        if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
                dbg("%s", "Invalid port \n");
@@ -2445,42 +2413,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
        switch (cmd) {
                /* return number of bytes available */
 
-       case TIOCINQ:
-               dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number);
-               return mos7840_get_bytes_avail(mos7840_port, argp);
-
-       case TIOCOUTQ:
-               dbg("%s (%d) TIOCOUTQ", __FUNCTION__, port->number);
-               return put_user(tty->driver->chars_in_buffer ?
-                               tty->driver->chars_in_buffer(tty) : 0,
-                               (int __user *)arg);
-
-       case TCFLSH:
-               retval = tty_check_change(tty);
-               if (retval)
-                       return retval;
-
-               ld = tty_ldisc_ref(tty);
-               switch (arg) {
-               case TCIFLUSH:
-                       if (ld && ld->flush_buffer)
-                               ld->flush_buffer(tty);
-                       break;
-               case TCIOFLUSH:
-                       if (ld && ld->flush_buffer)
-                               ld->flush_buffer(tty);
-                       /* fall through */
-               case TCOFLUSH:
-                       if (tty->driver->flush_buffer)
-                               tty->driver->flush_buffer(tty);
-                       break;
-               default:
-                       tty_ldisc_deref(ld);
-                       return -EINVAL;
-               }
-               tty_ldisc_deref(ld);
-               return 0;
-
        case TIOCSERGETLSR:
                dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
                return mos7840_get_lsr_info(mos7840_port, argp);
index 90701111d746158e3a444340928621e66e5d4861..7f337c9aeb5fe9ba13c5c58dd2bf1b3f2c5e4052 100644 (file)
@@ -37,9 +37,10 @@ static void navman_read_int_callback(struct urb *urb)
        struct usb_serial_port *port = urb->context;
        unsigned char *data = urb->transfer_buffer;
        struct tty_struct *tty;
+       int status = urb->status;
        int result;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -48,11 +49,11 @@ static void navman_read_int_callback(struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, urb->status);
+                   __FUNCTION__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, urb->status);
+                   __FUNCTION__, status);
                goto exit;
        }
 
index 00afc1712c391336163f4f0b72b83a115cb5aeb5..ee94d9616d82c8ff64869b58b46c56d08e5599aa 100644 (file)
@@ -1,10 +1,9 @@
 /*
  * USB ZyXEL omni.net LCD PLUS 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
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
+ *     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.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
@@ -201,14 +200,15 @@ static void omninet_read_bulk_callback (struct urb *urb)
        struct usb_serial_port  *port   = (struct usb_serial_port *)urb->context;
        unsigned char           *data   = urb->transfer_buffer;
        struct omninet_header   *header = (struct omninet_header *) &data[0];
-
+       int status = urb->status;
        int i;
        int result;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
@@ -312,12 +312,14 @@ static void omninet_write_bulk_callback (struct urb *urb)
 {
 /*     struct omninet_header   *header = (struct omninet_header  *) urb->transfer_buffer; */
        struct usb_serial_port  *port   = (struct usb_serial_port *) urb->context;
+       int status = urb->status;
 
        dbg("%s - port %0x\n", __FUNCTION__, port->number);
 
        port->write_urb_busy = 0;
-       if (urb->status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
index 5d3999e3ff614663dd8dab01f1c794b7c5b7a2d6..84c12b5f12715675148551bbee25ca5be5ae2b19 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/module.h>
+#include <linux/bitops.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
@@ -240,6 +241,7 @@ struct option_port_private {
        /* Output endpoints and buffer for this port */
        struct urb *out_urbs[N_OUT_URB];
        char out_buffer[N_OUT_URB][OUT_BUFLEN];
+       unsigned long out_busy;         /* Bit vector of URBs in use */
 
        /* Settings for the port */
        int rts_state;  /* Handshaking pins (outputs) */
@@ -370,7 +372,7 @@ static int option_write(struct usb_serial_port *port,
                        todo = OUT_BUFLEN;
 
                this_urb = portdata->out_urbs[i];
-               if (this_urb->status == -EINPROGRESS) {
+               if (test_and_set_bit(i, &portdata->out_busy)) {
                        if (time_before(jiffies,
                                        portdata->tx_start_time[i] + 10 * HZ))
                                continue;
@@ -394,6 +396,7 @@ static int option_write(struct usb_serial_port *port,
                        dbg("usb_submit_urb %p (write bulk) failed "
                                "(%d, has %d)", this_urb,
                                err, this_urb->status);
+                       clear_bit(i, &portdata->out_busy);
                        continue;
                }
                portdata->tx_start_time[i] = jiffies;
@@ -413,15 +416,16 @@ static void option_indat_callback(struct urb *urb)
        struct usb_serial_port *port;
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
+       int status = urb->status;
 
        dbg("%s: %p", __FUNCTION__, urb);
 
        endpoint = usb_pipeendpoint(urb->pipe);
        port = (struct usb_serial_port *) urb->context;
 
-       if (urb->status) {
+       if (status) {
                dbg("%s: nonzero status: %d on endpoint %02x.",
-                   __FUNCTION__, urb->status, endpoint);
+                   __FUNCTION__, status, endpoint);
        } else {
                tty = port->tty;
                if (urb->actual_length) {
@@ -433,7 +437,7 @@ static void option_indat_callback(struct urb *urb)
                }
 
                /* Resubmit urb so we continue receiving */
-               if (port->open_count && urb->status != -ESHUTDOWN) {
+               if (port->open_count && status != -ESHUTDOWN) {
                        err = usb_submit_urb(urb, GFP_ATOMIC);
                        if (err)
                                printk(KERN_ERR "%s: resubmit read urb failed. "
@@ -446,17 +450,29 @@ static void option_indat_callback(struct urb *urb)
 static void option_outdat_callback(struct urb *urb)
 {
        struct usb_serial_port *port;
+       struct option_port_private *portdata;
+       int i;
 
        dbg("%s", __FUNCTION__);
 
        port = (struct usb_serial_port *) urb->context;
 
        usb_serial_port_softint(port);
+
+       portdata = usb_get_serial_port_data(port);
+       for (i = 0; i < N_OUT_URB; ++i) {
+               if (portdata->out_urbs[i] == urb) {
+                       smp_mb__before_clear_bit();
+                       clear_bit(i, &portdata->out_busy);
+                       break;
+               }
+       }
 }
 
 static void option_instat_callback(struct urb *urb)
 {
        int err;
+       int status = urb->status;
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
        struct option_port_private *portdata = usb_get_serial_port_data(port);
        struct usb_serial *serial = port->serial;
@@ -464,7 +480,7 @@ static void option_instat_callback(struct urb *urb)
        dbg("%s", __FUNCTION__);
        dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
 
-       if (urb->status == 0) {
+       if (status == 0) {
                struct usb_ctrlrequest *req_pkt =
                                (struct usb_ctrlrequest *)urb->transfer_buffer;
 
@@ -495,10 +511,10 @@ static void option_instat_callback(struct urb *urb)
                                req_pkt->bRequestType,req_pkt->bRequest);
                }
        } else
-               dbg("%s: error %d", __FUNCTION__, urb->status);
+               dbg("%s: error %d", __FUNCTION__, status);
 
        /* Resubmit urb so we continue receiving IRQ data */
-       if (urb->status != -ESHUTDOWN) {
+       if (status != -ESHUTDOWN) {
                urb->dev = serial->dev;
                err = usb_submit_urb(urb, GFP_ATOMIC);
                if (err)
@@ -518,7 +534,7 @@ static int option_write_room(struct usb_serial_port *port)
 
        for (i=0; i < N_OUT_URB; i++) {
                this_urb = portdata->out_urbs[i];
-               if (this_urb && this_urb->status != -EINPROGRESS)
+               if (this_urb && !test_bit(i, &portdata->out_busy))
                        data_len += OUT_BUFLEN;
        }
 
@@ -537,7 +553,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port)
 
        for (i=0; i < N_OUT_URB; i++) {
                this_urb = portdata->out_urbs[i];
-               if (this_urb && this_urb->status == -EINPROGRESS)
+               if (this_urb && test_bit(i, &portdata->out_busy))
                        data_len += this_urb->transfer_buffer_length;
        }
        dbg("%s: %d", __FUNCTION__, data_len);
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
new file mode 100644 (file)
index 0000000..d7db71e
--- /dev/null
@@ -0,0 +1,1342 @@
+/*
+ * Ours Technology Inc. OTi-6858 USB to serial adapter driver.
+ *
+ * Copyleft  (C) 2007 Kees Lemmens (adapted for kernel 2.6.20)
+ * Copyright (C) 2006 Tomasz Michal Lukaszewski (FIXME: add e-mail)
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2003 IBM Corp.
+ *
+ * Many thanks to the authors of pl2303 driver: all functions in this file
+ * are heavily based on pl2303 code, buffering code is a 1-to-1 copy.
+ *
+ * Warning! You use this driver on your own risk! The only official
+ * description of this device I have is datasheet from manufacturer,
+ * and it doesn't contain almost any information needed to write a driver.
+ * Almost all knowlegde used while writing this driver was gathered by:
+ *  - analyzing traffic between device and the M$ Windows 2000 driver,
+ *  - trying different bit combinations and checking pin states
+ *    with a voltmeter,
+ *  - receiving malformed frames and producing buffer overflows
+ *    to learn how errors are reported,
+ * So, THIS CODE CAN DESTROY OTi-6858 AND ANY OTHER DEVICES, THAT ARE
+ * CONNECTED TO IT!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * TODO:
+ *  - implement correct flushing for ioctls and oti6858_close()
+ *  - check how errors (rx overflow, parity error, framing error) are reported
+ *  - implement oti6858_break_ctl()
+ *  - implement more ioctls
+ *  - test/implement flow control
+ *  - allow setting custom baud rates
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <asm/uaccess.h>
+#include "oti6858.h"
+
+#define OTI6858_DESCRIPTION \
+       "Ours Technology Inc. OTi-6858 USB to serial adapter driver"
+#define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>"
+#define OTI6858_VERSION "0.1"
+
+static struct usb_device_id id_table [] = {
+       { USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) },
+       { }
+};
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver oti6858_driver = {
+       .name =         "oti6858",
+       .probe =        usb_serial_probe,
+       .disconnect =   usb_serial_disconnect,
+       .id_table =     id_table,
+       .no_dynamic_id =        1,
+};
+
+static int debug;
+
+
+/* buffering code, copied from pl2303 driver */
+#define PL2303_BUF_SIZE                1024
+#define PL2303_TMP_BUF_SIZE    1024
+
+struct pl2303_buf {
+       unsigned int    buf_size;
+       char            *buf_buf;
+       char            *buf_get;
+       char            *buf_put;
+};
+
+/* requests */
+#define        OTI6858_REQ_GET_STATUS          (USB_DIR_IN | USB_TYPE_VENDOR | 0x00)
+#define        OTI6858_REQ_T_GET_STATUS        0x01
+
+#define        OTI6858_REQ_SET_LINE            (USB_DIR_OUT | USB_TYPE_VENDOR | 0x00)
+#define        OTI6858_REQ_T_SET_LINE          0x00
+
+#define        OTI6858_REQ_CHECK_TXBUFF        (USB_DIR_IN | USB_TYPE_VENDOR | 0x01)
+#define        OTI6858_REQ_T_CHECK_TXBUFF      0x00
+
+/* format of the control packet */
+struct oti6858_control_pkt {
+       u16     divisor;        /* baud rate = 96000000 / (16 * divisor), LE */
+#define OTI6858_MAX_BAUD_RATE  3000000
+       u8      frame_fmt;
+#define FMT_STOP_BITS_MASK     0xc0
+#define FMT_STOP_BITS_1                0x00
+#define FMT_STOP_BITS_2                0x40    /* 1.5 stop bits if FMT_DATA_BITS_5 */
+#define FMT_PARITY_MASK                0x38
+#define FMT_PARITY_NONE                0x00
+#define FMT_PARITY_ODD         0x08
+#define FMT_PARITY_EVEN                0x18
+#define FMT_PARITY_MARK                0x28
+#define FMT_PARITY_SPACE       0x38
+#define FMT_DATA_BITS_MASK     0x03
+#define FMT_DATA_BITS_5                0x00
+#define FMT_DATA_BITS_6                0x01
+#define FMT_DATA_BITS_7                0x02
+#define FMT_DATA_BITS_8                0x03
+       u8      something;      /* always equals 0x43 */
+       u8      control;        /* settings of flow control lines */
+#define CONTROL_MASK           0x0c
+#define CONTROL_DTR_HIGH       0x08
+#define CONTROL_RTS_HIGH       0x04
+       u8      tx_status;
+#define        TX_BUFFER_EMPTIED       0x09
+       u8      pin_state;
+#define PIN_MASK               0x3f
+#define PIN_RTS                        0x20    /* output pin */
+#define PIN_CTS                        0x10    /* input pin, active low */
+#define PIN_DSR                        0x08    /* input pin, active low */
+#define PIN_DTR                        0x04    /* output pin */
+#define PIN_RI                 0x02    /* input pin, active low */
+#define PIN_DCD                        0x01    /* input pin, active low */
+       u8      rx_bytes_avail;         /* number of bytes in rx buffer */;
+};
+
+#define OTI6858_CTRL_PKT_SIZE  sizeof(struct oti6858_control_pkt)
+#define OTI6858_CTRL_EQUALS_PENDING(a, priv) \
+       (    ((a)->divisor == (priv)->pending_setup.divisor) \
+         && ((a)->control == (priv)->pending_setup.control) \
+         && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt) )
+
+/* function prototypes */
+static int oti6858_open(struct usb_serial_port *port, struct file *filp);
+static void oti6858_close(struct usb_serial_port *port, struct file *filp);
+static void oti6858_set_termios(struct usb_serial_port *port,
+                               struct ktermios *old);
+static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+                       unsigned int cmd, unsigned long arg);
+static void oti6858_read_int_callback(struct urb *urb);
+static void oti6858_read_bulk_callback(struct urb *urb);
+static void oti6858_write_bulk_callback(struct urb *urb);
+static int oti6858_write(struct usb_serial_port *port,
+                       const unsigned char *buf, int count);
+static int oti6858_write_room(struct usb_serial_port *port);
+static void oti6858_break_ctl(struct usb_serial_port *port, int break_state);
+static int oti6858_chars_in_buffer(struct usb_serial_port *port);
+static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file);
+static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+                               unsigned int set, unsigned int clear);
+static int oti6858_startup(struct usb_serial *serial);
+static void oti6858_shutdown(struct usb_serial *serial);
+
+/* functions operating on buffers */
+static struct pl2303_buf *pl2303_buf_alloc(unsigned int size);
+static void pl2303_buf_free(struct pl2303_buf *pb);
+static void pl2303_buf_clear(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+                                       unsigned int count);
+static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+                                       unsigned int count);
+
+
+/* device info */
+static struct usb_serial_driver oti6858_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "oti6858",
+       },
+       .id_table =             id_table,
+       .num_interrupt_in =     1,
+       .num_bulk_in =          1,
+       .num_bulk_out =         1,
+       .num_ports =            1,
+       .open =                 oti6858_open,
+       .close =                oti6858_close,
+       .write =                oti6858_write,
+       .ioctl =                oti6858_ioctl,
+       .break_ctl =            oti6858_break_ctl,
+       .set_termios =          oti6858_set_termios,
+       .tiocmget =             oti6858_tiocmget,
+       .tiocmset =             oti6858_tiocmset,
+       .read_bulk_callback =   oti6858_read_bulk_callback,
+       .read_int_callback =    oti6858_read_int_callback,
+       .write_bulk_callback =  oti6858_write_bulk_callback,
+       .write_room =           oti6858_write_room,
+       .chars_in_buffer =      oti6858_chars_in_buffer,
+       .attach =               oti6858_startup,
+       .shutdown =             oti6858_shutdown,
+};
+
+struct oti6858_private {
+       spinlock_t lock;
+
+       struct pl2303_buf *buf;
+       struct oti6858_control_pkt status;
+
+       struct {
+               u8 read_urb_in_use;
+               u8 write_urb_in_use;
+               u8 termios_initialized;
+       } flags;
+       struct delayed_work delayed_write_work;
+
+       struct {
+               u16 divisor;
+               u8 frame_fmt;
+               u8 control;
+       } pending_setup;
+       u8 transient;
+       u8 setup_done;
+       struct delayed_work delayed_setup_work;
+
+       wait_queue_head_t intr_wait;
+        struct usb_serial_port *port;   /* USB port with which associated */
+};
+
+#undef dbg
+/* #define dbg(format, arg...) printk(KERN_INFO "%s: " format "\n", __FILE__, ## arg) */
+#define dbg(format, arg...) printk(KERN_INFO "" format "\n", ## arg)
+
+static void setup_line(struct work_struct *work)
+{
+       struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_setup_work.work);
+       struct usb_serial_port *port = priv->port;
+       struct oti6858_control_pkt *new_setup;
+       unsigned long flags;
+       int result;
+
+       dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+       if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+               dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
+               /* we will try again */
+               schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+               return;
+       }
+
+       result = usb_control_msg(port->serial->dev,
+                               usb_rcvctrlpipe(port->serial->dev, 0),
+                               OTI6858_REQ_T_GET_STATUS,
+                               OTI6858_REQ_GET_STATUS,
+                               0, 0,
+                               new_setup, OTI6858_CTRL_PKT_SIZE,
+                               100);
+
+       if (result != OTI6858_CTRL_PKT_SIZE) {
+               dev_err(&port->dev, "%s(): error reading status", __FUNCTION__);
+               kfree(new_setup);
+               /* we will try again */
+               schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+               return;
+       }
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (!OTI6858_CTRL_EQUALS_PENDING(new_setup, priv)) {
+               new_setup->divisor = priv->pending_setup.divisor;
+               new_setup->control = priv->pending_setup.control;
+               new_setup->frame_fmt = priv->pending_setup.frame_fmt;
+
+               spin_unlock_irqrestore(&priv->lock, flags);
+               result = usb_control_msg(port->serial->dev,
+                                       usb_sndctrlpipe(port->serial->dev, 0),
+                                       OTI6858_REQ_T_SET_LINE,
+                                       OTI6858_REQ_SET_LINE,
+                                       0, 0,
+                                       new_setup, OTI6858_CTRL_PKT_SIZE,
+                                       100);
+       } else {
+               spin_unlock_irqrestore(&priv->lock, flags);
+               result = 0;
+       }
+       kfree(new_setup);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (result != OTI6858_CTRL_PKT_SIZE)
+               priv->transient = 0;
+       priv->setup_done = 1;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       dbg("%s(): submitting interrupt urb", __FUNCTION__);
+       port->interrupt_in_urb->dev = port->serial->dev;
+       result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+       if (result != 0) {
+               dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+                               " with error %d\n", __FUNCTION__, result);
+       }
+}
+
+void send_data(struct work_struct *work)
+{
+       struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_write_work.work);
+       struct usb_serial_port *port = priv->port;
+       int count = 0, result;
+       unsigned long flags;
+       unsigned char allow;
+
+       dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (priv->flags.write_urb_in_use) {
+               spin_unlock_irqrestore(&priv->lock, flags);
+               schedule_delayed_work(&priv->delayed_write_work, msecs_to_jiffies(2));
+               return;
+       }
+       priv->flags.write_urb_in_use = 1;
+
+       count = pl2303_buf_data_avail(priv->buf);
+       spin_unlock_irqrestore(&priv->lock, flags);
+       if (count > port->bulk_out_size)
+               count = port->bulk_out_size;
+
+       if (count != 0) {
+               result = usb_control_msg(port->serial->dev,
+                               usb_rcvctrlpipe(port->serial->dev, 0),
+                               OTI6858_REQ_T_CHECK_TXBUFF,
+                               OTI6858_REQ_CHECK_TXBUFF,
+                               count, 0, &allow, 1, 100);
+               if (result != 1 || allow != 0)
+                       count = 0;
+       }
+
+       if (count == 0) {
+               priv->flags.write_urb_in_use = 0;
+
+               dbg("%s(): submitting interrupt urb", __FUNCTION__);
+               port->interrupt_in_urb->dev = port->serial->dev;
+               result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+               if (result != 0) {
+                       dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+                               " with error %d\n", __FUNCTION__, result);
+               }
+               return;
+       }
+
+       spin_lock_irqsave(&priv->lock, flags);
+       pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, count);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       port->write_urb->transfer_buffer_length = count;
+       port->write_urb->dev = port->serial->dev;
+       result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+       if (result != 0) {
+               dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+                              " with error %d\n", __FUNCTION__, result);
+               priv->flags.write_urb_in_use = 0;
+       }
+
+       usb_serial_port_softint(port);
+}
+
+static int oti6858_startup(struct usb_serial *serial)
+{
+        struct usb_serial_port *port = serial->port[0];
+        struct oti6858_private *priv;
+       int i;
+
+       for (i = 0; i < serial->num_ports; ++i) {
+               priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL);
+               if (!priv)
+                       break;
+               priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE);
+               if (priv->buf == NULL) {
+                       kfree(priv);
+                       break;
+               }
+
+               spin_lock_init(&priv->lock);
+               init_waitqueue_head(&priv->intr_wait);
+//             INIT_WORK(&priv->setup_work, setup_line, serial->port[i]);
+//             INIT_WORK(&priv->write_work, send_data, serial->port[i]);
+               priv->port = port;
+               INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
+               INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
+
+               usb_set_serial_port_data(serial->port[i], priv);
+       }
+       if (i == serial->num_ports)
+               return 0;
+
+       for (--i; i >= 0; --i) {
+               priv = usb_get_serial_port_data(serial->port[i]);
+               pl2303_buf_free(priv->buf);
+               kfree(priv);
+               usb_set_serial_port_data(serial->port[i], NULL);
+       }
+       return -ENOMEM;
+}
+
+static int oti6858_write(struct usb_serial_port *port,
+                       const unsigned char *buf, int count)
+{
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       dbg("%s(port = %d, count = %d)", __FUNCTION__, port->number, count);
+
+       if (!count)
+               return count;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       count = pl2303_buf_put(priv->buf, buf, count);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return count;
+}
+
+static int oti6858_write_room(struct usb_serial_port *port)
+{
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       int room = 0;
+       unsigned long flags;
+
+       dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       room = pl2303_buf_space_avail(priv->buf);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return room;
+}
+
+static int oti6858_chars_in_buffer(struct usb_serial_port *port)
+{
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       int chars = 0;
+       unsigned long flags;
+
+       dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       chars = pl2303_buf_data_avail(priv->buf);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return chars;
+}
+
+static void oti6858_set_termios(struct usb_serial_port *port,
+                               struct ktermios *old_termios)
+{
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned int cflag;
+       u8 frame_fmt, control;
+       u16 divisor;
+       int br;
+
+       dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+       if ((!port->tty) || (!port->tty->termios)) {
+               dbg("%s(): no tty structures", __FUNCTION__);
+               return;
+       }
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (!priv->flags.termios_initialized) {
+               *(port->tty->termios) = tty_std_termios;
+               port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+               priv->flags.termios_initialized = 1;
+       }
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       cflag = port->tty->termios->c_cflag;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       divisor = priv->pending_setup.divisor;
+       frame_fmt = priv->pending_setup.frame_fmt;
+       control = priv->pending_setup.control;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       frame_fmt &= ~FMT_DATA_BITS_MASK;
+       switch (cflag & CSIZE) {
+               case CS5:
+                       frame_fmt |= FMT_DATA_BITS_5;
+                       break;
+               case CS6:
+                       frame_fmt |= FMT_DATA_BITS_6;
+                       break;
+               case CS7:
+                       frame_fmt |= FMT_DATA_BITS_7;
+                       break;
+               default:
+               case CS8:
+                       frame_fmt |= FMT_DATA_BITS_8;
+                       break;
+       }
+
+       /* manufacturer claims that this device can work with baud rates
+        * up to 3 Mbps; I've tested it only on 115200 bps, so I can't
+        * guarantee that any other baud rate will work (especially
+        * the higher ones)
+        */
+       br = tty_get_baud_rate(port->tty);
+       if (br == 0) {
+               divisor = 0;
+       } else if (br <= OTI6858_MAX_BAUD_RATE) {
+               int real_br;
+
+               divisor = (96000000 + 8 * br) / (16 * br);
+               real_br = 96000000 / (16 * divisor);
+               if ((((real_br - br) * 100 + br - 1) / br) > 2) {
+                       dbg("%s(): baud rate %d is invalid", __FUNCTION__, br);
+                       return;
+               }
+               divisor = cpu_to_le16(divisor);
+       } else {
+               dbg("%s(): baud rate %d is too high", __FUNCTION__, br);
+               return;
+       }
+
+       frame_fmt &= ~FMT_STOP_BITS_MASK;
+       if ((cflag & CSTOPB) != 0) {
+               frame_fmt |= FMT_STOP_BITS_2;
+       } else {
+               frame_fmt |= FMT_STOP_BITS_1;
+       }
+
+       frame_fmt &= ~FMT_PARITY_MASK;
+       if ((cflag & PARENB) != 0) {
+               if ((cflag & PARODD) != 0) {
+                       frame_fmt |= FMT_PARITY_ODD;
+               } else {
+                       frame_fmt |= FMT_PARITY_EVEN;
+               }
+       } else {
+               frame_fmt |= FMT_PARITY_NONE;
+       }
+
+       control &= ~CONTROL_MASK;
+       if ((cflag & CRTSCTS) != 0)
+               control |= (CONTROL_DTR_HIGH | CONTROL_RTS_HIGH);
+
+       /* change control lines if we are switching to or from B0 */
+       /* FIXME:
+       spin_lock_irqsave(&priv->lock, flags);
+       control = priv->line_control;
+       if ((cflag & CBAUD) == B0)
+               priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+       else
+               priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+       if (control != priv->line_control) {
+               control = priv->line_control;
+               spin_unlock_irqrestore(&priv->lock, flags);
+               set_control_lines(serial->dev, control);
+       } else {
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+       */
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (divisor != priv->pending_setup.divisor
+                       || control != priv->pending_setup.control
+                       || frame_fmt != priv->pending_setup.frame_fmt) {
+               priv->pending_setup.divisor = divisor;
+               priv->pending_setup.control = control;
+               priv->pending_setup.frame_fmt = frame_fmt;
+       }
+       spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+{
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       struct ktermios tmp_termios;
+       struct usb_serial *serial = port->serial;
+       struct oti6858_control_pkt *buf;
+       unsigned long flags;
+       int result;
+
+       dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+       usb_clear_halt(serial->dev, port->write_urb->pipe);
+       usb_clear_halt(serial->dev, port->read_urb->pipe);
+
+       if (port->open_count != 1)
+               return 0;
+
+       if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+               dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
+               return -ENOMEM;
+       }
+
+       result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+                               OTI6858_REQ_T_GET_STATUS,
+                               OTI6858_REQ_GET_STATUS,
+                               0, 0,
+                               buf, OTI6858_CTRL_PKT_SIZE,
+                               100);
+       if (result != OTI6858_CTRL_PKT_SIZE) {
+               /* assume default (after power-on reset) values */
+               buf->divisor = cpu_to_le16(0x009c);     /* 38400 bps */
+               buf->frame_fmt = 0x03;  /* 8N1 */
+               buf->something = 0x43;
+               buf->control = 0x4c;    /* DTR, RTS */
+               buf->tx_status = 0x00;
+               buf->pin_state = 0x5b;  /* RTS, CTS, DSR, DTR, RI, DCD */
+               buf->rx_bytes_avail = 0x00;
+       }
+
+       spin_lock_irqsave(&priv->lock, flags);
+       memcpy(&priv->status, buf, OTI6858_CTRL_PKT_SIZE);
+       priv->pending_setup.divisor = buf->divisor;
+       priv->pending_setup.frame_fmt = buf->frame_fmt;
+       priv->pending_setup.control = buf->control;
+       spin_unlock_irqrestore(&priv->lock, flags);
+       kfree(buf);
+
+       dbg("%s(): submitting interrupt urb", __FUNCTION__);
+       port->interrupt_in_urb->dev = serial->dev;
+       result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+       if (result != 0) {
+               dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+                              " with error %d\n", __FUNCTION__, result);
+               oti6858_close(port, NULL);
+               return -EPROTO;
+       }
+
+       /* setup termios */
+       if (port->tty)
+               oti6858_set_termios(port, &tmp_termios);
+
+       return 0;
+}
+
+static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+{
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       long timeout;
+       wait_queue_t wait;
+
+       dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+       /* wait for data to drain from the buffer */
+       spin_lock_irqsave(&priv->lock, flags);
+       timeout = 30 * HZ;      /* PL2303_CLOSING_WAIT */
+       init_waitqueue_entry(&wait, current);
+       add_wait_queue(&port->tty->write_wait, &wait);
+       dbg("%s(): entering wait loop", __FUNCTION__);
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (pl2303_buf_data_avail(priv->buf) == 0
+               || timeout == 0 || signal_pending(current)
+               || !usb_get_intfdata(port->serial->interface))  /* disconnect */
+                       break;
+               spin_unlock_irqrestore(&priv->lock, flags);
+               timeout = schedule_timeout(timeout);
+               spin_lock_irqsave(&priv->lock, flags);
+       }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(&port->tty->write_wait, &wait);
+       dbg("%s(): after wait loop", __FUNCTION__);
+
+       /* clear out any remaining data in the buffer */
+       pl2303_buf_clear(priv->buf);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       /* wait for characters to drain from the device */
+       /* (this is long enough for the entire 256 byte */
+       /* pl2303 hardware buffer to drain with no flow */
+       /* control for data rates of 1200 bps or more, */
+       /* for lower rates we should really know how much */
+       /* data is in the buffer to compute a delay */
+       /* that is not unnecessarily long) */
+       /* FIXME
+       bps = tty_get_baud_rate(port->tty);
+       if (bps > 1200)
+               timeout = max((HZ*2560)/bps,HZ/10);
+       else
+       */
+               timeout = 2*HZ;
+       schedule_timeout_interruptible(timeout);
+       dbg("%s(): after schedule_timeout_interruptible()", __FUNCTION__);
+
+       /* cancel scheduled setup */
+       cancel_delayed_work(&priv->delayed_setup_work);
+       cancel_delayed_work(&priv->delayed_write_work);
+       flush_scheduled_work();
+
+       /* shutdown our urbs */
+       dbg("%s(): shutting down urbs", __FUNCTION__);
+       usb_kill_urb(port->write_urb);
+       usb_kill_urb(port->read_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       /*
+       if (port->tty && (port->tty->termios->c_cflag) & HUPCL) {
+               // drop DTR and RTS
+               spin_lock_irqsave(&priv->lock, flags);
+               priv->pending_setup.control &= ~CONTROL_MASK;
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+       */
+}
+
+static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+                               unsigned int set, unsigned int clear)
+{
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       u8 control;
+
+       dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)",
+                               __FUNCTION__, port->number, set, clear);
+
+       if (!usb_get_intfdata(port->serial->interface))
+               return -ENODEV;
+
+       /* FIXME: check if this is correct (active high/low) */
+       spin_lock_irqsave(&priv->lock, flags);
+       control = priv->pending_setup.control;
+       if ((set & TIOCM_RTS) != 0)
+               control |= CONTROL_RTS_HIGH;
+       if ((set & TIOCM_DTR) != 0)
+               control |= CONTROL_DTR_HIGH;
+       if ((clear & TIOCM_RTS) != 0)
+               control &= ~CONTROL_RTS_HIGH;
+       if ((clear & TIOCM_DTR) != 0)
+               control &= ~CONTROL_DTR_HIGH;
+
+       if (control != priv->pending_setup.control) {
+               priv->pending_setup.control = control;
+       }
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return 0;
+}
+
+static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned pin_state;
+       unsigned result = 0;
+
+       dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+       if (!usb_get_intfdata(port->serial->interface))
+               return -ENODEV;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       pin_state = priv->status.pin_state & PIN_MASK;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       /* FIXME: check if this is correct (active high/low) */
+       if ((pin_state & PIN_RTS) != 0)
+               result |= TIOCM_RTS;
+       if ((pin_state & PIN_CTS) != 0)
+               result |= TIOCM_CTS;
+       if ((pin_state & PIN_DSR) != 0)
+               result |= TIOCM_DSR;
+       if ((pin_state & PIN_DTR) != 0)
+               result |= TIOCM_DTR;
+       if ((pin_state & PIN_RI) != 0)
+               result |= TIOCM_RI;
+       if ((pin_state & PIN_DCD) != 0)
+               result |= TIOCM_CD;
+
+       dbg("%s() = 0x%08x", __FUNCTION__, result);
+
+       return result;
+}
+
+static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+{
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned int prev, status;
+       unsigned int changed;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       prev = priv->status.pin_state;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       while (1) {
+               wait_event_interruptible(priv->intr_wait, priv->status.pin_state != prev);
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+
+               spin_lock_irqsave(&priv->lock, flags);
+               status = priv->status.pin_state & PIN_MASK;
+               spin_unlock_irqrestore(&priv->lock, flags);
+
+               changed = prev ^ status;
+               /* FIXME: check if this is correct (active high/low) */
+               if (    ((arg & TIOCM_RNG) && (changed & PIN_RI)) ||
+                       ((arg & TIOCM_DSR) && (changed & PIN_DSR)) ||
+                       ((arg & TIOCM_CD)  && (changed & PIN_DCD)) ||
+                       ((arg & TIOCM_CTS) && (changed & PIN_CTS))) {
+                               return 0;
+               }
+               prev = status;
+       }
+
+       /* NOTREACHED */
+       return 0;
+}
+
+static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+                       unsigned int cmd, unsigned long arg)
+{
+       void __user *user_arg = (void __user *) arg;
+       unsigned int x;
+
+       dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
+                               __FUNCTION__, port->number, cmd, arg);
+
+       switch (cmd) {
+               case TCGETS:
+                       if (copy_to_user(user_arg, port->tty->termios,
+                                               sizeof(struct ktermios))) {
+                               return -EFAULT;
+                       }
+                       return 0;
+
+               case TCSETS:
+               case TCSETSW:   /* FIXME: this is not the same! */
+               case TCSETSF:   /* FIXME: this is not the same! */
+                       if (copy_from_user(port->tty->termios, user_arg,
+                                               sizeof(struct ktermios))) {
+                               return -EFAULT;
+                       }
+                       oti6858_set_termios(port, NULL);
+                       return 0;
+
+               case TCFLSH:
+                       /* FIXME */
+                       return 0;
+
+               case TIOCMBIS:
+                       if (copy_from_user(&x, user_arg, sizeof(x)))
+                               return -EFAULT;
+                       return oti6858_tiocmset(port, NULL, x, 0);
+
+               case TIOCMBIC:
+                       if (copy_from_user(&x, user_arg, sizeof(x)))
+                               return -EFAULT;
+                       return oti6858_tiocmset(port, NULL, 0, x);
+
+               case TIOCGSERIAL:
+                       if (copy_to_user(user_arg, port->tty->termios,
+                                               sizeof(struct ktermios))) {
+                               return -EFAULT;
+                       }
+                        return 0;
+
+               case TIOCSSERIAL:
+                       if (copy_from_user(port->tty->termios, user_arg,
+                                               sizeof(struct ktermios))) {
+                               return -EFAULT;
+                       }
+                       oti6858_set_termios(port, NULL);
+                       return 0;
+
+               case TIOCMIWAIT:
+                       dbg("%s(): TIOCMIWAIT", __FUNCTION__);
+                       return wait_modem_info(port, arg);
+
+               default:
+                       dbg("%s(): 0x%04x not supported", __FUNCTION__, cmd);
+                       break;
+       }
+
+       return -ENOIOCTLCMD;
+}
+
+static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
+{
+       int state;
+
+       dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+       state = (break_state == 0) ? 0 : 1;
+       dbg("%s(): turning break %s", __FUNCTION__, state ? "on" : "off");
+
+       /* FIXME */
+/*
+       result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
+                                 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
+                                 0, NULL, 0, 100);
+       if (result != 0)
+               dbg("%s(): error sending break", __FUNCTION__);
+ */
+}
+
+static void oti6858_shutdown(struct usb_serial *serial)
+{
+       struct oti6858_private *priv;
+       int i;
+
+       dbg("%s()", __FUNCTION__);
+
+       for (i = 0; i < serial->num_ports; ++i) {
+               priv = usb_get_serial_port_data(serial->port[i]);
+               if (priv) {
+                       pl2303_buf_free(priv->buf);
+                       kfree(priv);
+                       usb_set_serial_port_data(serial->port[i], NULL);
+               }
+       }
+}
+
+static void oti6858_read_int_callback(struct urb *urb)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       int transient = 0, can_recv = 0, resubmit = 1;
+       int status = urb->status;
+
+       dbg("%s(port = %d, status = %d)",
+                               __FUNCTION__, port->number, status);
+
+       switch (status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s(): urb shutting down with status: %d",
+                                       __FUNCTION__, status);
+               return;
+       default:
+               dbg("%s(): nonzero urb status received: %d",
+                                       __FUNCTION__, status);
+               break;
+       }
+
+       if (status == 0 && urb->actual_length == OTI6858_CTRL_PKT_SIZE) {
+               struct oti6858_control_pkt *xs = urb->transfer_buffer;
+               unsigned long flags;
+
+               spin_lock_irqsave(&priv->lock, flags);
+
+               if (!priv->transient) {
+                       if (!OTI6858_CTRL_EQUALS_PENDING(xs, priv)) {
+                               if (xs->rx_bytes_avail == 0) {
+                                       priv->transient = 4;
+                                       priv->setup_done = 0;
+                                       resubmit = 0;
+                                       dbg("%s(): scheduling setup_line()",
+                                           __FUNCTION__);
+                                       schedule_delayed_work(&priv->delayed_setup_work, 0);
+                               }
+                       }
+               } else {
+                       if (OTI6858_CTRL_EQUALS_PENDING(xs, priv)) {
+                               priv->transient = 0;
+                       } else if (!priv->setup_done) {
+                               resubmit = 0;
+                       } else if (--priv->transient == 0) {
+                               if (xs->rx_bytes_avail == 0) {
+                                       priv->transient = 4;
+                                       priv->setup_done = 0;
+                                       resubmit = 0;
+                                       dbg("%s(): scheduling setup_line()",
+                                           __FUNCTION__);
+                                       schedule_delayed_work(&priv->delayed_setup_work, 0);
+                               }
+                       }
+               }
+
+               if (!priv->transient) {
+                       if (xs->pin_state != priv->status.pin_state)
+                               wake_up_interruptible(&priv->intr_wait);
+                       memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
+               }
+
+               if (!priv->transient && xs->rx_bytes_avail != 0) {
+                       can_recv = xs->rx_bytes_avail;
+                       priv->flags.read_urb_in_use = 1;
+               }
+
+               transient = priv->transient;
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+
+       if (can_recv) {
+               int result;
+
+               port->read_urb->dev = port->serial->dev;
+               result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+               if (result != 0) {
+                       priv->flags.read_urb_in_use = 0;
+                       dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+                                       " error %d\n", __FUNCTION__, result);
+               } else {
+                       resubmit = 0;
+               }
+       } else if (!transient) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&priv->lock, flags);
+               if (priv->flags.write_urb_in_use == 0
+                               && pl2303_buf_data_avail(priv->buf) != 0) {
+                       schedule_delayed_work(&priv->delayed_write_work,0);
+                       resubmit = 0;
+               }
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+
+       if (resubmit) {
+               int result;
+
+//             dbg("%s(): submitting interrupt urb", __FUNCTION__);
+               urb->dev = port->serial->dev;
+               result = usb_submit_urb(urb, GFP_ATOMIC);
+               if (result != 0) {
+                       dev_err(&urb->dev->dev,
+                                       "%s(): usb_submit_urb() failed with"
+                                       " error %d\n", __FUNCTION__, result);
+               }
+       }
+}
+
+static void oti6858_read_bulk_callback(struct urb *urb)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       struct tty_struct *tty;
+       unsigned char *data = urb->transfer_buffer;
+       unsigned long flags;
+       int i, result;
+       int status = urb->status;
+       char tty_flag;
+
+       dbg("%s(port = %d, status = %d)",
+                               __FUNCTION__, port->number, status);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       priv->flags.read_urb_in_use = 0;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       if (status != 0) {
+               if (!port->open_count) {
+                       dbg("%s(): port is closed, exiting", __FUNCTION__);
+                       return;
+               }
+               /*
+               if (status == -EPROTO) {
+                       // PL2303 mysteriously fails with -EPROTO reschedule the read
+                       dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);
+                       result = usb_submit_urb(urb, GFP_ATOMIC);
+                       if (result)
+                               dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+                       return;
+               }
+               */
+               dbg("%s(): unable to handle the error, exiting", __FUNCTION__);
+               return;
+       }
+
+       // get tty_flag from status
+       tty_flag = TTY_NORMAL;
+
+/* FIXME: probably, errors will be signalled using interrupt pipe! */
+/*
+       // break takes precedence over parity,
+       // which takes precedence over framing errors
+       if (status & UART_BREAK_ERROR )
+               tty_flag = TTY_BREAK;
+       else if (status & UART_PARITY_ERROR)
+               tty_flag = TTY_PARITY;
+       else if (status & UART_FRAME_ERROR)
+               tty_flag = TTY_FRAME;
+       dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
+*/
+
+       tty = port->tty;
+       if (tty != NULL && urb->actual_length > 0) {
+               tty_buffer_request_room(tty, urb->actual_length);
+               for (i = 0; i < urb->actual_length; ++i)
+                       tty_insert_flip_char(tty, data[i], tty_flag);
+               tty_flip_buffer_push(tty);
+       }
+
+       // schedule the interrupt urb if we are still open */
+       if (port->open_count != 0) {
+               port->interrupt_in_urb->dev = port->serial->dev;
+               result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+               if (result != 0) {
+                       dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+                                       " error %d\n", __FUNCTION__, result);
+               }
+       }
+}
+
+static void oti6858_write_bulk_callback(struct urb *urb)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+       struct oti6858_private *priv = usb_get_serial_port_data(port);
+       int status = urb->status;
+       int result;
+
+       dbg("%s(port = %d, status = %d)",
+                               __FUNCTION__, port->number, status);
+
+       switch (status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s(): urb shutting down with status: %d",
+                                       __FUNCTION__, status);
+               priv->flags.write_urb_in_use = 0;
+               return;
+       default:
+               /* error in the urb, so we have to resubmit it */
+               dbg("%s(): nonzero write bulk status received: %d",
+                                       __FUNCTION__, status);
+               dbg("%s(): overflow in write", __FUNCTION__);
+
+               port->write_urb->transfer_buffer_length = 1;
+               port->write_urb->dev = port->serial->dev;
+               result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+               if (result) {
+                       dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+                                       " error %d\n", __FUNCTION__, result);
+               } else {
+                       return;
+               }
+       }
+
+       priv->flags.write_urb_in_use = 0;
+
+       // schedule the interrupt urb if we are still open */
+       port->interrupt_in_urb->dev = port->serial->dev;
+       dbg("%s(): submitting interrupt urb", __FUNCTION__);
+       result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+       if (result != 0) {
+               dev_err(&port->dev, "%s(): failed submitting int urb,"
+                                       " error %d\n", __FUNCTION__, result);
+       }
+}
+
+
+/*
+ * pl2303_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
+{
+       struct pl2303_buf *pb;
+
+       if (size == 0)
+               return NULL;
+
+       pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+       if (pb == NULL)
+               return NULL;
+
+       pb->buf_buf = kmalloc(size, GFP_KERNEL);
+       if (pb->buf_buf == NULL) {
+               kfree(pb);
+               return NULL;
+       }
+
+       pb->buf_size = size;
+       pb->buf_get = pb->buf_put = pb->buf_buf;
+
+       return pb;
+}
+
+/*
+ * pl2303_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void pl2303_buf_free(struct pl2303_buf *pb)
+{
+       if (pb) {
+               kfree(pb->buf_buf);
+               kfree(pb);
+       }
+}
+
+/*
+ * pl2303_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void pl2303_buf_clear(struct pl2303_buf *pb)
+{
+       if (pb != NULL) {
+               /* equivalent to a get of all data available */
+               pb->buf_get = pb->buf_put;
+       }
+}
+
+/*
+ * pl2303_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
+{
+       if (pb == NULL)
+               return 0;
+       return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_space_avail
+ *
+ * Return the number of bytes of space available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
+{
+       if (pb == NULL)
+               return 0;
+       return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+                                       unsigned int count)
+{
+       unsigned int len;
+
+       if (pb == NULL)
+               return 0;
+
+       len  = pl2303_buf_space_avail(pb);
+       if (count > len)
+               count = len;
+
+       if (count == 0)
+               return 0;
+
+       len = pb->buf_buf + pb->buf_size - pb->buf_put;
+       if (count > len) {
+               memcpy(pb->buf_put, buf, len);
+               memcpy(pb->buf_buf, buf+len, count - len);
+               pb->buf_put = pb->buf_buf + count - len;
+       } else {
+               memcpy(pb->buf_put, buf, count);
+               if (count < len)
+                       pb->buf_put += count;
+               else /* count == len */
+                       pb->buf_put = pb->buf_buf;
+       }
+
+       return count;
+}
+
+/*
+ * pl2303_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+                                       unsigned int count)
+{
+       unsigned int len;
+
+       if (pb == NULL)
+               return 0;
+
+       len = pl2303_buf_data_avail(pb);
+       if (count > len)
+               count = len;
+
+       if (count == 0)
+               return 0;
+
+       len = pb->buf_buf + pb->buf_size - pb->buf_get;
+       if (count > len) {
+               memcpy(buf, pb->buf_get, len);
+               memcpy(buf+len, pb->buf_buf, count - len);
+               pb->buf_get = pb->buf_buf + count - len;
+       } else {
+               memcpy(buf, pb->buf_get, count);
+               if (count < len)
+                       pb->buf_get += count;
+               else /* count == len */
+                       pb->buf_get = pb->buf_buf;
+       }
+
+       return count;
+}
+
+/* module description and (de)initialization */
+
+static int __init oti6858_init(void)
+{
+       int retval;
+
+       if ((retval = usb_serial_register(&oti6858_device)) == 0) {
+               if ((retval = usb_register(&oti6858_driver)) != 0)
+                       usb_serial_deregister(&oti6858_device);
+               else
+                       return 0;
+       }
+
+       return retval;
+}
+
+static void __exit oti6858_exit(void)
+{
+       usb_deregister(&oti6858_driver);
+       usb_serial_deregister(&oti6858_device);
+}
+
+module_init(oti6858_init);
+module_exit(oti6858_exit);
+
+MODULE_DESCRIPTION(OTI6858_DESCRIPTION);
+MODULE_AUTHOR(OTI6858_AUTHOR);
+MODULE_VERSION(OTI6858_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "enable debug output");
+
diff --git a/drivers/usb/serial/oti6858.h b/drivers/usb/serial/oti6858.h
new file mode 100644 (file)
index 0000000..704ac3a
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Ours Technology Inc. OTi-6858 USB to serial adapter 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __LINUX_USB_SERIAL_OTI6858_H
+#define __LINUX_USB_SERIAL_OTI6858_H
+
+#define OTI6858_VENDOR_ID      0x0ea0
+#define OTI6858_PRODUCT_ID     0x6858
+
+#endif
index 83dfae93a45db37278ee130e3b99fb30a2328a23..f9f85f56f0db48a0c3f67262be1f64a0e81ee6f2 100644 (file)
@@ -1,14 +1,14 @@
 /*
  * Prolific PL2303 USB to serial adaptor driver
  *
- * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001-2007 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (C) 2003 IBM Corp.
  *
  * Original driver for 2.2.x by anonymous
  *
- *     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.
+ *     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.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
@@ -484,15 +484,6 @@ static void pl2303_set_termios(struct usb_serial_port *port,
        spin_unlock_irqrestore(&priv->lock, flags);
 
        cflag = port->tty->termios->c_cflag;
-       /* check that they really want us to change something */
-       if (old_termios) {
-               if ((cflag == old_termios->c_cflag) &&
-                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
-                    RELEVANT_IFLAG(old_termios->c_iflag))) {
-                       dbg("%s - nothing to change...", __FUNCTION__);
-                       return;
-               }
-       }
 
        buf = kzalloc(7, GFP_KERNEL);
        if (!buf) {
@@ -517,29 +508,7 @@ static void pl2303_set_termios(struct usb_serial_port *port,
                dbg("%s - data bits = %d", __FUNCTION__, buf[6]);
        }
 
-       baud = 0;
-       switch (cflag & CBAUD) {
-               case B0:        baud = 0;       break;
-               case B75:       baud = 75;      break;
-               case B150:      baud = 150;     break;
-               case B300:      baud = 300;     break;
-               case B600:      baud = 600;     break;
-               case B1200:     baud = 1200;    break;
-               case B1800:     baud = 1800;    break;
-               case B2400:     baud = 2400;    break;
-               case B4800:     baud = 4800;    break;
-               case B9600:     baud = 9600;    break;
-               case B19200:    baud = 19200;   break;
-               case B38400:    baud = 38400;   break;
-               case B57600:    baud = 57600;   break;
-               case B115200:   baud = 115200;  break;
-               case B230400:   baud = 230400;  break;
-               case B460800:   baud = 460800;  break;
-               default:
-                       dev_err(&port->dev, "pl2303 driver does not support"
-                               " the baudrate requested (fix it)\n");
-                       break;
-       }
+       baud = tty_get_baud_rate(port->tty);;
        dbg("%s - baud = %d", __FUNCTION__, baud);
        if (baud) {
                buf[0] = baud & 0xff;
@@ -617,6 +586,13 @@ static void pl2303_set_termios(struct usb_serial_port *port,
                                    VENDOR_WRITE_REQUEST_TYPE,
                                    0x0, index, NULL, 0, 100);
                dbg("0x40:0x1:0x0:0x%x  %d", index, i);
+       } else {
+               i = usb_control_msg(serial->dev,
+                                   usb_sndctrlpipe(serial->dev, 0),
+                                   VENDOR_WRITE_REQUEST,
+                                   VENDOR_WRITE_REQUEST_TYPE,
+                                   0x0, 0x0, NULL, 0, 100);
+               dbg ("0x40:0x1:0x0:0x0  %d", i);
        }
 
        kfree(buf);
@@ -954,11 +930,12 @@ static void pl2303_read_int_callback(struct urb *urb)
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
        unsigned char *data = urb->transfer_buffer;
        unsigned int actual_length = urb->actual_length;
-       int status;
+       int status = urb->status;
+       int retval;
 
        dbg("%s (%d)", __FUNCTION__, port->number);
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -967,11 +944,11 @@ static void pl2303_read_int_callback(struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d", __FUNCTION__,
-                   urb->status);
+                   status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d", __FUNCTION__,
-                   urb->status);
+                   status);
                goto exit;
        }
 
@@ -981,11 +958,11 @@ static void pl2303_read_int_callback(struct urb *urb)
        pl2303_update_line_status(port, data, actual_length);
 
 exit:
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status)
+       retval = usb_submit_urb(urb, GFP_ATOMIC);
+       if (retval)
                dev_err(&urb->dev->dev,
                        "%s - usb_submit_urb failed with result %d\n",
-                       __FUNCTION__, status);
+                       __FUNCTION__, retval);
 }
 
 static void pl2303_read_bulk_callback(struct urb *urb)
@@ -997,23 +974,23 @@ static void pl2303_read_bulk_callback(struct urb *urb)
        unsigned long flags;
        int i;
        int result;
-       u8 status;
+       int status = urb->status;
+       u8 line_status;
        char tty_flag;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - urb status = %d", __FUNCTION__, status);
                if (!port->open_count) {
                        dbg("%s - port is closed, exiting.", __FUNCTION__);
                        return;
                }
-               if (urb->status == -EPROTO) {
+               if (status == -EPROTO) {
                        /* PL2303 mysteriously fails with -EPROTO reschedule
                         * the read */
                        dbg("%s - caught -EPROTO, resubmitting the urb",
                            __FUNCTION__);
-                       urb->status = 0;
                        urb->dev = port->serial->dev;
                        result = usb_submit_urb(urb, GFP_ATOMIC);
                        if (result)
@@ -1033,18 +1010,18 @@ static void pl2303_read_bulk_callback(struct urb *urb)
        tty_flag = TTY_NORMAL;
 
        spin_lock_irqsave(&priv->lock, flags);
-       status = priv->line_status;
+       line_status = priv->line_status;
        priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
        spin_unlock_irqrestore(&priv->lock, flags);
        wake_up_interruptible(&priv->delta_msr_wait);
 
        /* break takes precedence over parity, */
        /* which takes precedence over framing errors */
-       if (status & UART_BREAK_ERROR )
+       if (line_status & UART_BREAK_ERROR )
                tty_flag = TTY_BREAK;
-       else if (status & UART_PARITY_ERROR)
+       else if (line_status & UART_PARITY_ERROR)
                tty_flag = TTY_PARITY;
-       else if (status & UART_FRAME_ERROR)
+       else if (line_status & UART_FRAME_ERROR)
                tty_flag = TTY_FRAME;
        dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
 
@@ -1052,7 +1029,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
        if (tty && urb->actual_length) {
                tty_buffer_request_room(tty, urb->actual_length + 1);
                /* overrun is special, not associated with a char */
-               if (status & UART_OVERRUN_ERROR)
+               if (line_status & UART_OVERRUN_ERROR)
                        tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                for (i = 0; i < urb->actual_length; ++i)
                        tty_insert_flip_char(tty, data[i], tty_flag);
@@ -1076,10 +1053,11 @@ static void pl2303_write_bulk_callback(struct urb *urb)
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        int result;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -1088,14 +1066,14 @@ static void pl2303_write_bulk_callback(struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d", __FUNCTION__,
-                   urb->status);
+                   status);
                priv->write_urb_in_use = 0;
                return;
        default:
                /* error in the urb, so we have to resubmit it */
                dbg("%s - Overflow in write", __FUNCTION__);
                dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
-                   urb->status);
+                   status);
                port->write_urb->transfer_buffer_length = 1;
                port->write_urb->dev = port->serial->dev;
                result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
index 5a03a3fc938693b1056031dd046015d1ce9d6631..86899d55d8d818fcc0b81e7cd0a67c2d7ec19c0b 100644 (file)
@@ -211,11 +211,13 @@ static void safe_read_bulk_callback (struct urb *urb)
        unsigned char length = urb->actual_length;
        int i;
        int result;
+       int status = urb->status;
 
        dbg ("%s", __FUNCTION__);
 
-       if (urb->status) {
-               dbg ("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
index ac1829c6e8f02da29aecc3a5383a0c1dfa7a2b2e..e7db20343d1a156a898fe51e27754d8929a8f890 100644 (file)
@@ -86,15 +86,14 @@ static int debug;
 #define N_IN_URB       4
 #define N_OUT_URB      4
 #define IN_BUFLEN      4096
-#define OUT_BUFLEN     128
 
 struct sierra_port_private {
+       spinlock_t lock;        /* lock the structure */
+       int outstanding_urbs;   /* number of out urbs in flight */
+
        /* Input endpoints and buffer for this port */
        struct urb *in_urbs[N_IN_URB];
        char in_buffer[N_IN_URB][IN_BUFLEN];
-       /* Output endpoints and buffer for this port */
-       struct urb *out_urbs[N_OUT_URB];
-       char out_buffer[N_OUT_URB][OUT_BUFLEN];
 
        /* Settings for the port */
        int rts_state;  /* Handshaking pins (outputs) */
@@ -103,8 +102,6 @@ struct sierra_port_private {
        int dsr_state;
        int dcd_state;
        int ri_state;
-
-       unsigned long tx_start_time[N_OUT_URB];
 };
 
 static int sierra_send_setup(struct usb_serial_port *port)
@@ -197,61 +194,98 @@ static int sierra_ioctl(struct usb_serial_port *port, struct file *file,
        return -ENOIOCTLCMD;
 }
 
+static void sierra_outdat_callback(struct urb *urb)
+{
+       struct usb_serial_port *port = urb->context;
+       struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+       int status = urb->status;
+       unsigned long flags;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* free up the transfer buffer, as usb_free_urb() does not do this */
+       kfree(urb->transfer_buffer);
+
+       if (status)
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, status);
+
+       spin_lock_irqsave(&portdata->lock, flags);
+       --portdata->outstanding_urbs;
+       spin_unlock_irqrestore(&portdata->lock, flags);
+
+       usb_serial_port_softint(port);
+}
+
 /* Write */
 static int sierra_write(struct usb_serial_port *port,
                        const unsigned char *buf, int count)
 {
-       struct sierra_port_private *portdata;
-       int i;
-       int left, todo;
-       struct urb *this_urb = NULL; /* spurious */
-       int err;
+       struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+       struct usb_serial *serial = port->serial;
+       unsigned long flags;
+       unsigned char *buffer;
+       struct urb *urb;
+       int status;
 
        portdata = usb_get_serial_port_data(port);
 
        dbg("%s: write (%d chars)", __FUNCTION__, count);
 
-       i = 0;
-       left = count;
-       for (i=0; left > 0 && i < N_OUT_URB; i++) {
-               todo = left;
-               if (todo > OUT_BUFLEN)
-                       todo = OUT_BUFLEN;
-
-               this_urb = portdata->out_urbs[i];
-               if (this_urb->status == -EINPROGRESS) {
-                       if (time_before(jiffies,
-                                       portdata->tx_start_time[i] + 10 * HZ))
-                               continue;
-                       usb_unlink_urb(this_urb);
-                       continue;
-               }
-               if (this_urb->status != 0)
-                       dbg("usb_write %p failed (err=%d)",
-                               this_urb, this_urb->status);
-
-               dbg("%s: endpoint %d buf %d", __FUNCTION__,
-                       usb_pipeendpoint(this_urb->pipe), i);
-
-               /* send the data */
-               memcpy (this_urb->transfer_buffer, buf, todo);
-               this_urb->transfer_buffer_length = todo;
-
-               this_urb->dev = port->serial->dev;
-               err = usb_submit_urb(this_urb, GFP_ATOMIC);
-               if (err) {
-                       dbg("usb_submit_urb %p (write bulk) failed "
-                               "(%d, has %d)", this_urb,
-                               err, this_urb->status);
-                       continue;
-               }
-               portdata->tx_start_time[i] = jiffies;
-               buf += todo;
-               left -= todo;
+       spin_lock_irqsave(&portdata->lock, flags);
+       if (portdata->outstanding_urbs > N_OUT_URB) {
+               spin_unlock_irqrestore(&portdata->lock, flags);
+               dbg("%s - write limit hit\n", __FUNCTION__);
+               return 0;
+       }
+       portdata->outstanding_urbs++;
+       spin_unlock_irqrestore(&portdata->lock, flags);
+
+       buffer = kmalloc(count, GFP_ATOMIC);
+       if (!buffer) {
+               dev_err(&port->dev, "out of memory\n");
+               count = -ENOMEM;
+               goto error_no_buffer;
+       }
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               dev_err(&port->dev, "no more free urbs\n");
+               count = -ENOMEM;
+               goto error_no_urb;
+       }
+
+       memcpy(buffer, buf, count);
+
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+
+       usb_fill_bulk_urb(urb, serial->dev,
+                         usb_sndbulkpipe(serial->dev,
+                                         port->bulk_out_endpointAddress),
+                         buffer, count, sierra_outdat_callback, port);
+
+       /* send it down the pipe */
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status) {
+               dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+                       "with status = %d\n", __FUNCTION__, status);
+               count = status;
+               goto error;
        }
 
-       count -= left;
-       dbg("%s: wrote (did %d)", __FUNCTION__, count);
+       /* we are done with this urb, so let the host driver
+        * really free it when it is finished with it */
+       usb_free_urb(urb);
+
+       return count;
+error:
+       usb_free_urb(urb);
+error_no_urb:
+       kfree(buffer);
+error_no_buffer:
+       spin_lock_irqsave(&portdata->lock, flags);
+       --portdata->outstanding_urbs;
+       spin_unlock_irqrestore(&portdata->lock, flags);
        return count;
 }
 
@@ -262,15 +296,16 @@ static void sierra_indat_callback(struct urb *urb)
        struct usb_serial_port *port;
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
+       int status = urb->status;
 
        dbg("%s: %p", __FUNCTION__, urb);
 
        endpoint = usb_pipeendpoint(urb->pipe);
        port = (struct usb_serial_port *) urb->context;
 
-       if (urb->status) {
+       if (status) {
                dbg("%s: nonzero status: %d on endpoint %02x.",
-                   __FUNCTION__, urb->status, endpoint);
+                   __FUNCTION__, status, endpoint);
        } else {
                tty = port->tty;
                if (urb->actual_length) {
@@ -282,30 +317,20 @@ static void sierra_indat_callback(struct urb *urb)
                }
 
                /* Resubmit urb so we continue receiving */
-               if (port->open_count && urb->status != -ESHUTDOWN) {
+               if (port->open_count && status != -ESHUTDOWN) {
                        err = usb_submit_urb(urb, GFP_ATOMIC);
                        if (err)
-                               printk(KERN_ERR "%s: resubmit read urb failed. "
-                                       "(%d)", __FUNCTION__, err);
+                               dev_err(&port->dev, "resubmit read urb failed."
+                                       "(%d)", err);
                }
        }
        return;
 }
 
-static void sierra_outdat_callback(struct urb *urb)
-{
-       struct usb_serial_port *port;
-
-       dbg("%s", __FUNCTION__);
-
-       port = (struct usb_serial_port *) urb->context;
-
-       usb_serial_port_softint(port);
-}
-
 static void sierra_instat_callback(struct urb *urb)
 {
        int err;
+       int status = urb->status;
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
        struct sierra_port_private *portdata = usb_get_serial_port_data(port);
        struct usb_serial *serial = port->serial;
@@ -313,7 +338,7 @@ static void sierra_instat_callback(struct urb *urb)
        dbg("%s", __FUNCTION__);
        dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
 
-       if (urb->status == 0) {
+       if (status == 0) {
                struct usb_ctrlrequest *req_pkt =
                                (struct usb_ctrlrequest *)urb->transfer_buffer;
 
@@ -344,10 +369,10 @@ static void sierra_instat_callback(struct urb *urb)
                                req_pkt->bRequestType,req_pkt->bRequest);
                }
        } else
-               dbg("%s: error %d", __FUNCTION__, urb->status);
+               dbg("%s: error %d", __FUNCTION__, status);
 
        /* Resubmit urb so we continue receiving IRQ data */
-       if (urb->status != -ESHUTDOWN) {
+       if (status != -ESHUTDOWN) {
                urb->dev = serial->dev;
                err = usb_submit_urb(urb, GFP_ATOMIC);
                if (err)
@@ -358,46 +383,42 @@ static void sierra_instat_callback(struct urb *urb)
 
 static int sierra_write_room(struct usb_serial_port *port)
 {
-       struct sierra_port_private *portdata;
-       int i;
-       int data_len = 0;
-       struct urb *this_urb;
+       struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+       unsigned long flags;
 
-       portdata = usb_get_serial_port_data(port);
+       dbg("%s - port %d", __FUNCTION__, port->number);
 
-       for (i=0; i < N_OUT_URB; i++) {
-               this_urb = portdata->out_urbs[i];
-               if (this_urb && this_urb->status != -EINPROGRESS)
-                       data_len += OUT_BUFLEN;
+       /* try to give a good number back based on if we have any free urbs at
+        * this point in time */
+       spin_lock_irqsave(&portdata->lock, flags);
+       if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) {
+               spin_unlock_irqrestore(&portdata->lock, flags);
+               dbg("%s - write limit hit\n", __FUNCTION__);
+               return 0;
        }
+       spin_unlock_irqrestore(&portdata->lock, flags);
 
-       dbg("%s: %d", __FUNCTION__, data_len);
-       return data_len;
+       return 2048;
 }
 
 static int sierra_chars_in_buffer(struct usb_serial_port *port)
 {
-       struct sierra_port_private *portdata;
-       int i;
-       int data_len = 0;
-       struct urb *this_urb;
-
-       portdata = usb_get_serial_port_data(port);
-
-       for (i=0; i < N_OUT_URB; i++) {
-               this_urb = portdata->out_urbs[i];
-               if (this_urb && this_urb->status == -EINPROGRESS)
-                       data_len += this_urb->transfer_buffer_length;
-       }
-       dbg("%s: %d", __FUNCTION__, data_len);
-       return data_len;
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /*
+        * We can't really account for how much data we
+        * have sent out, but hasn't made it through to the
+        * device as we can't see the backend here, so just
+        * tell the tty layer that everything is flushed.
+        */
+       return 0;
 }
 
 static int sierra_open(struct usb_serial_port *port, struct file *filp)
 {
        struct sierra_port_private *portdata;
        struct usb_serial *serial = port->serial;
-       int i, err;
+       int i;
        struct urb *urb;
        int result;
        __u16 set_mode_dzero = 0x0000;
@@ -413,7 +434,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
        /* Reset low level data toggle and start reading from endpoints */
        for (i = 0; i < N_IN_URB; i++) {
                urb = portdata->in_urbs[i];
-               if (! urb)
+               if (!urb)
                        continue;
                if (urb->dev != serial->dev) {
                        dbg("%s: dev %p != %p", __FUNCTION__,
@@ -427,24 +448,13 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
                 */
                usb_clear_halt(urb->dev, urb->pipe);
 
-               err = usb_submit_urb(urb, GFP_KERNEL);
-               if (err) {
-                       dbg("%s: submit urb %d failed (%d) %d",
-                               __FUNCTION__, i, err,
-                               urb->transfer_buffer_length);
+               result = usb_submit_urb(urb, GFP_KERNEL);
+               if (result) {
+                       dev_err(&port->dev, "submit urb %d failed (%d) %d",
+                               i, result, urb->transfer_buffer_length);
                }
        }
 
-       /* Reset low level data toggle on out endpoints */
-       for (i = 0; i < N_OUT_URB; i++) {
-               urb = portdata->out_urbs[i];
-               if (! urb)
-                       continue;
-               urb->dev = serial->dev;
-               /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-                               usb_pipeout(urb->pipe), 0); */
-       }
-
        port->tty->low_latency = 1;
 
        /* set mode to D0 */
@@ -455,7 +465,14 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
 
        sierra_send_setup(port);
 
-       return (0);
+       /* start up the interrupt endpoint if we have one */
+       if (port->interrupt_in_urb) {
+               result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+               if (result)
+                       dev_err(&port->dev, "submit irq_in urb failed %d",
+                               result);
+       }
+       return 0;
 }
 
 static void sierra_close(struct usb_serial_port *port, struct file *filp)
@@ -475,71 +492,21 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
 
                /* Stop reading/writing urbs */
                for (i = 0; i < N_IN_URB; i++)
-                       usb_unlink_urb(portdata->in_urbs[i]);
-               for (i = 0; i < N_OUT_URB; i++)
-                       usb_unlink_urb(portdata->out_urbs[i]);
+                       usb_kill_urb(portdata->in_urbs[i]);
        }
-       port->tty = NULL;
-}
-
-/* Helper functions used by sierra_setup_urbs */
-static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint,
-                                   int dir, void *ctx, char *buf, int len,
-                                   usb_complete_t callback)
-{
-       struct urb *urb;
-
-       if (endpoint == -1)
-               return NULL;            /* endpoint not needed */
-
-       urb = usb_alloc_urb(0, GFP_KERNEL);             /* No ISO */
-       if (urb == NULL) {
-               dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
-               return NULL;
-       }
-
-               /* Fill URB using supplied data. */
-       usb_fill_bulk_urb(urb, serial->dev,
-                     usb_sndbulkpipe(serial->dev, endpoint) | dir,
-                     buf, len, callback, ctx);
-
-       return urb;
-}
 
-/* Setup urbs */
-static void sierra_setup_urbs(struct usb_serial *serial)
-{
-       int i,j;
-       struct usb_serial_port *port;
-       struct sierra_port_private *portdata;
-
-       dbg("%s", __FUNCTION__);
+       usb_kill_urb(port->interrupt_in_urb);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = usb_get_serial_port_data(port);
-
-       /* Do indat endpoints first */
-               for (j = 0; j < N_IN_URB; ++j) {
-                       portdata->in_urbs[j] = sierra_setup_urb (serial,
-                       port->bulk_in_endpointAddress, USB_DIR_IN, port,
-                       portdata->in_buffer[j], IN_BUFLEN, sierra_indat_callback);
-               }
-
-               /* outdat endpoints */
-               for (j = 0; j < N_OUT_URB; ++j) {
-                       portdata->out_urbs[j] = sierra_setup_urb (serial,
-                       port->bulk_out_endpointAddress, USB_DIR_OUT, port,
-                       portdata->out_buffer[j], OUT_BUFLEN, sierra_outdat_callback);
-               }
-       }
+       port->tty = NULL;
 }
 
 static int sierra_startup(struct usb_serial *serial)
 {
-       int i, err;
        struct usb_serial_port *port;
        struct sierra_port_private *portdata;
+       struct urb *urb;
+       int i;
+       int j;
 
        dbg("%s", __FUNCTION__);
 
@@ -550,22 +517,31 @@ static int sierra_startup(struct usb_serial *serial)
                if (!portdata) {
                        dbg("%s: kmalloc for sierra_port_private (%d) failed!.",
                                        __FUNCTION__, i);
-                       return (1);
+                       return -ENOMEM;
                }
+               spin_lock_init(&portdata->lock);
 
                usb_set_serial_port_data(port, portdata);
 
-               if (! port->interrupt_in_urb)
-                       continue;
-               err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-               if (err)
-                       dbg("%s: submit irq_in urb failed %d",
-                               __FUNCTION__, err);
+               /* initialize the in urbs */
+               for (j = 0; j < N_IN_URB; ++j) {
+                       urb = usb_alloc_urb(0, GFP_KERNEL);
+                       if (urb == NULL) {
+                               dbg("%s: alloc for in port failed.",
+                                   __FUNCTION__);
+                               continue;
+                       }
+                       /* Fill URB using supplied data. */
+                       usb_fill_bulk_urb(urb, serial->dev,
+                                         usb_rcvbulkpipe(serial->dev,
+                                               port->bulk_in_endpointAddress),
+                                         portdata->in_buffer[j], IN_BUFLEN,
+                                         sierra_indat_callback, port);
+                       portdata->in_urbs[j] = urb;
+               }
        }
 
-       sierra_setup_urbs(serial);
-
-       return (0);
+       return 0;
 }
 
 static void sierra_shutdown(struct usb_serial *serial)
@@ -576,22 +552,6 @@ static void sierra_shutdown(struct usb_serial *serial)
 
        dbg("%s", __FUNCTION__);
 
-       /* Stop reading/writing urbs */
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               if (!port)
-                       continue;
-               portdata = usb_get_serial_port_data(port);
-               if (!portdata)
-                       continue;
-
-               for (j = 0; j < N_IN_URB; j++)
-                       usb_unlink_urb(portdata->in_urbs[j]);
-               for (j = 0; j < N_OUT_URB; j++)
-                       usb_unlink_urb(portdata->out_urbs[j]);
-       }
-
-       /* Now free them */
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
                if (!port)
@@ -601,25 +561,12 @@ static void sierra_shutdown(struct usb_serial *serial)
                        continue;
 
                for (j = 0; j < N_IN_URB; j++) {
-                       if (portdata->in_urbs[j]) {
-                               usb_free_urb(portdata->in_urbs[j]);
-                               portdata->in_urbs[j] = NULL;
-                       }
+                       usb_kill_urb(portdata->in_urbs[j]);
+                       usb_free_urb(portdata->in_urbs[j]);
+                       portdata->in_urbs[j] = NULL;
                }
-               for (j = 0; j < N_OUT_URB; j++) {
-                       if (portdata->out_urbs[j]) {
-                               usb_free_urb(portdata->out_urbs[j]);
-                               portdata->out_urbs[j] = NULL;
-                       }
-               }
-       }
-
-       /* Now free per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               if (!port)
-                       continue;
-               kfree(usb_get_serial_port_data(port));
+               kfree(portdata);
+               usb_set_serial_port_data(port, NULL);
        }
 }
 
index 3d505fd0645b04e5740c1f597ef827b57ac68666..f98626ae75fea01a773d379f85b94af4acefea07 100644 (file)
@@ -1112,22 +1112,24 @@ static void ti_interrupt_callback(struct urb *urb)
        int length = urb->actual_length;
        int port_number;
        int function;
-       int status;
+       int status = urb->status;
+       int retval;
        __u8 msr;
 
        dbg("%s", __FUNCTION__);
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                break;
        case -ECONNRESET:
        case -ENOENT:
        case -ESHUTDOWN:
-               dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down, %d", __FUNCTION__, status);
                tdev->td_urb_error = 1;
                return;
        default:
-               dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status);
+               dev_err(dev, "%s - nonzero urb status, %d\n",
+                       __FUNCTION__, status);
                tdev->td_urb_error = 1;
                goto exit;
        }
@@ -1175,9 +1177,10 @@ static void ti_interrupt_callback(struct urb *urb)
        }
 
 exit:
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status)
-               dev_err(dev, "%s - resubmit interrupt urb failed, %d\n", __FUNCTION__, status);
+       retval = usb_submit_urb(urb, GFP_ATOMIC);
+       if (retval)
+               dev_err(dev, "%s - resubmit interrupt urb failed, %d\n",
+                       __FUNCTION__, retval);
 }
 
 
@@ -1186,30 +1189,32 @@ static void ti_bulk_in_callback(struct urb *urb)
        struct ti_port *tport = (struct ti_port *)urb->context;
        struct usb_serial_port *port = tport->tp_port;
        struct device *dev = &urb->dev->dev;
-       int status = 0;
+       int status = urb->status;
+       int retval = 0;
 
        dbg("%s", __FUNCTION__);
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                break;
        case -ECONNRESET:
        case -ENOENT:
        case -ESHUTDOWN:
-               dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down, %d", __FUNCTION__, status);
                tport->tp_tdev->td_urb_error = 1;
                wake_up_interruptible(&tport->tp_write_wait);
                return;
        default:
-               dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status );
+               dev_err(dev, "%s - nonzero urb status, %d\n",
+                       __FUNCTION__, status );
                tport->tp_tdev->td_urb_error = 1;
                wake_up_interruptible(&tport->tp_write_wait);
        }
 
-       if (urb->status == -EPIPE)
+       if (status == -EPIPE)
                goto exit;
 
-       if (urb->status) {
+       if (status) {
                dev_err(dev, "%s - stopping read!\n", __FUNCTION__);
                return;
        }
@@ -1234,13 +1239,14 @@ exit:
        spin_lock(&tport->tp_lock);
        if (tport->tp_read_urb_state == TI_READ_URB_RUNNING) {
                urb->dev = port->serial->dev;
-               status = usb_submit_urb(urb, GFP_ATOMIC);
+               retval = usb_submit_urb(urb, GFP_ATOMIC);
        } else if (tport->tp_read_urb_state == TI_READ_URB_STOPPING) {
                tport->tp_read_urb_state = TI_READ_URB_STOPPED;
        }
        spin_unlock(&tport->tp_lock);
-       if (status)
-               dev_err(dev, "%s - resubmit read urb failed, %d\n", __FUNCTION__, status);
+       if (retval)
+               dev_err(dev, "%s - resubmit read urb failed, %d\n",
+                       __FUNCTION__, retval);
 }
 
 
@@ -1249,23 +1255,25 @@ static void ti_bulk_out_callback(struct urb *urb)
        struct ti_port *tport = (struct ti_port *)urb->context;
        struct usb_serial_port *port = tport->tp_port;
        struct device *dev = &urb->dev->dev;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
        tport->tp_write_urb_in_use = 0;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                break;
        case -ECONNRESET:
        case -ENOENT:
        case -ESHUTDOWN:
-               dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down, %d", __FUNCTION__, status);
                tport->tp_tdev->td_urb_error = 1;
                wake_up_interruptible(&tport->tp_write_wait);
                return;
        default:
-               dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status);
+               dev_err(dev, "%s - nonzero urb status, %d\n",
+                       __FUNCTION__, status);
                tport->tp_tdev->td_urb_error = 1;
                wake_up_interruptible(&tport->tp_write_wait);
        }
index 87f378806db645d5d7897e0f56ecb7ceb885e092..a3665659d13b32636914368429c0be0d6998e35d 100644 (file)
@@ -46,6 +46,8 @@ static struct usb_driver usb_serial_driver = {
        .name =         "usbserial",
        .probe =        usb_serial_probe,
        .disconnect =   usb_serial_disconnect,
+       .suspend =      usb_serial_suspend,
+       .resume =       usb_serial_resume,
        .no_dynamic_id =        1,
 };
 
@@ -120,11 +122,9 @@ static void return_serial(struct usb_serial *serial)
        if (serial == NULL)
                return;
 
-       spin_lock(&table_lock);
        for (i = 0; i < serial->num_ports; ++i) {
                serial_table[serial->minor + i] = NULL;
        }
-       spin_unlock(&table_lock);
 }
 
 static void destroy_serial(struct kref *kref)
@@ -172,7 +172,9 @@ static void destroy_serial(struct kref *kref)
 
 void usb_serial_put(struct usb_serial *serial)
 {
+       spin_lock(&table_lock);
        kref_put(&serial->kref, destroy_serial);
+       spin_unlock(&table_lock);
 }
 
 /*****************************************************************************
@@ -1069,6 +1071,35 @@ void usb_serial_disconnect(struct usb_interface *interface)
        dev_info(dev, "device disconnected\n");
 }
 
+int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct usb_serial *serial = usb_get_intfdata(intf);
+       struct usb_serial_port *port;
+       int i, r = 0;
+
+       if (serial) {
+               for (i = 0; i < serial->num_ports; ++i) {
+                       port = serial->port[i];
+                       if (port)
+                               kill_traffic(port);
+               }
+       }
+
+       if (serial->type->suspend)
+               serial->type->suspend(serial, message);
+
+       return r;
+}
+EXPORT_SYMBOL(usb_serial_suspend);
+
+int usb_serial_resume(struct usb_interface *intf)
+{
+       struct usb_serial *serial = usb_get_intfdata(intf);
+
+       return serial->type->resume(serial);
+}
+EXPORT_SYMBOL(usb_serial_resume);
+
 static const struct tty_operations serial_ops = {
        .open =                 serial_open,
        .close =                serial_close,
index ffbe601cde2a563d34f3921eaee2934b92c56f53..7d84a7647e81efeec0c025df2ecf783ade3b16aa 100644 (file)
@@ -5,9 +5,9 @@
  *     Copyright (C) 1999 - 2004
  *         Greg Kroah-Hartman (greg@kroah.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.
+ *     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.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
@@ -273,7 +273,8 @@ struct visor_private {
        int bytes_in;
        int bytes_out;
        int outstanding_urbs;
-       int throttled;
+       unsigned char throttled;
+       unsigned char actually_throttled;
 };
 
 /* number of outstanding urbs to prevent userspace DoS from happening */
@@ -484,16 +485,17 @@ static void visor_write_bulk_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct visor_private *priv = usb_get_serial_port_data(port);
+       int status = urb->status;
        unsigned long flags;
 
        /* free up the transfer buffer, as usb_free_urb() does not do this */
        kfree (urb->transfer_buffer);
 
        dbg("%s - port %d", __FUNCTION__, port->number);
-       
-       if (urb->status)
+
+       if (status)
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, urb->status);
+                   __FUNCTION__, status);
 
        spin_lock_irqsave(&priv->lock, flags);
        --priv->outstanding_urbs;
@@ -508,15 +510,16 @@ static void visor_read_bulk_callback (struct urb *urb)
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct visor_private *priv = usb_get_serial_port_data(port);
        unsigned char *data = urb->transfer_buffer;
+       int status = urb->status;
        struct tty_struct *tty;
-       unsigned long flags;
-       int throttled;
        int result;
+       int available_room;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
@@ -524,17 +527,20 @@ static void visor_read_bulk_callback (struct urb *urb)
 
        tty = port->tty;
        if (tty && urb->actual_length) {
-               tty_buffer_request_room(tty, urb->actual_length);
-               tty_insert_flip_string(tty, data, urb->actual_length);
-               tty_flip_buffer_push(tty);
+               available_room = tty_buffer_request_room(tty, urb->actual_length);
+               if (available_room) {
+                       tty_insert_flip_string(tty, data, available_room);
+                       tty_flip_buffer_push(tty);
+               }
+               spin_lock(&priv->lock);
+               priv->bytes_in += available_room;
+
+       } else {
+               spin_lock(&priv->lock);
        }
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->bytes_in += urb->actual_length;
-       throttled = priv->throttled;
-       spin_unlock_irqrestore(&priv->lock, flags);
 
        /* Continue trying to always read if we should */
-       if (!throttled) {
+       if (!priv->throttled) {
                usb_fill_bulk_urb (port->read_urb, port->serial->dev,
                                   usb_rcvbulkpipe(port->serial->dev,
                                                   port->bulk_in_endpointAddress),
@@ -544,16 +550,19 @@ static void visor_read_bulk_callback (struct urb *urb)
                result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
                if (result)
                        dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+       } else {
+               priv->actually_throttled = 1;
        }
-       return;
+       spin_unlock(&priv->lock);
 }
 
 static void visor_read_int_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       int status = urb->status;
        int result;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -562,11 +571,11 @@ static void visor_read_int_callback (struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, urb->status);
+                   __FUNCTION__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, urb->status);
+                   __FUNCTION__, status);
                goto exit;
        }
 
@@ -608,6 +617,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
        dbg("%s - port %d", __FUNCTION__, port->number);
        spin_lock_irqsave(&priv->lock, flags);
        priv->throttled = 0;
+       priv->actually_throttled = 0;
        spin_unlock_irqrestore(&priv->lock, flags);
 
        port->read_urb->dev = port->serial->dev;
@@ -938,14 +948,6 @@ static void visor_set_termios (struct usb_serial_port *port, struct ktermios *ol
        }
 
        cflag = port->tty->termios->c_cflag;
-       /* check that they really want us to change something */
-       if (old_termios) {
-               if ((cflag == old_termios->c_cflag) &&
-                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-                       dbg("%s - nothing to change...", __FUNCTION__);
-                       return;
-               }
-       }
 
        /* get the byte size */
        switch (cflag & CSIZE) {
index 27c5f8f9a2d5e9907f49e094826167eb8c5ddd6d..cc8b44c08712c67c1c41448c18b17ff23950228a 100644 (file)
@@ -74,6 +74,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/termbits.h>
 #include <linux/usb.h>
@@ -203,7 +204,7 @@ static struct usb_serial_driver whiteheat_device = {
 
 
 struct whiteheat_command_private {
-       spinlock_t              lock;
+       struct mutex            mutex;
        __u8                    port_running;
        __u8                    command_finished;
        wait_queue_head_t       wait_command;   /* for handling sleeping while waiting for a command to finish */
@@ -232,6 +233,7 @@ struct whiteheat_private {
        struct usb_serial_port  *port;
        struct list_head        tx_urbs_free;
        struct list_head        tx_urbs_submitted;
+       struct mutex            deathwarrant;
 };
 
 
@@ -425,6 +427,7 @@ static int whiteheat_attach (struct usb_serial *serial)
                }
 
                spin_lock_init(&info->lock);
+               mutex_init(&info->deathwarrant);
                info->flags = 0;
                info->mcr = 0;
                INIT_WORK(&info->rx_work, rx_data_softint);
@@ -495,7 +498,7 @@ static int whiteheat_attach (struct usb_serial *serial)
                goto no_command_private;
        }
 
-       spin_lock_init(&command_info->lock);
+       mutex_init(&command_info->mutex);
        command_info->port_running = 0;
        init_waitqueue_head(&command_info->wait_command);
        usb_set_serial_port_data(command_port, command_info);
@@ -654,7 +657,6 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
        struct urb *urb;
        struct list_head *tmp;
        struct list_head *tmp2;
-       unsigned long flags;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
        
@@ -683,24 +685,32 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
 
        firm_close(port);
 
+printk(KERN_ERR"Before processing rx_urbs_submitted.\n");
        /* shutdown our bulk reads and writes */
-       spin_lock_irqsave(&info->lock, flags);
+       mutex_lock(&info->deathwarrant);
+       spin_lock_irq(&info->lock);
        list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
                wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
                urb = wrap->urb;
+               list_del(tmp);
+               spin_unlock_irq(&info->lock);
                usb_kill_urb(urb);
-               list_move(tmp, &info->rx_urbs_free);
+               spin_lock_irq(&info->lock);
+               list_add(tmp, &info->rx_urbs_free);
        }
        list_for_each_safe(tmp, tmp2, &info->rx_urb_q)
                list_move(tmp, &info->rx_urbs_free);
-
        list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) {
                wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
                urb = wrap->urb;
+               list_del(tmp);
+               spin_unlock_irq(&info->lock);
                usb_kill_urb(urb);
-               list_move(tmp, &info->tx_urbs_free);
+               spin_lock_irq(&info->lock);
+               list_add(tmp, &info->tx_urbs_free);
        }
-       spin_unlock_irqrestore(&info->lock, flags);
+       spin_unlock_irq(&info->lock);
+       mutex_unlock(&info->deathwarrant);
 
        stop_command_port(port->serial);
 
@@ -872,7 +882,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
 }
 
 
-static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios)
 {
        dbg("%s -port %d", __FUNCTION__, port->number);
 
@@ -881,15 +891,6 @@ static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios
                goto exit;
        }
        
-       /* check that they really want us to change something */
-       if (old_termios) {
-               if ((port->tty->termios->c_cflag == old_termios->c_cflag) &&
-                   (port->tty->termios->c_iflag == old_termios->c_iflag)) {
-                       dbg("%s - nothing to change...", __FUNCTION__);
-                       goto exit;
-               }
-       }
-
        firm_setup_port(port);
 
 exit:
@@ -920,7 +921,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
        spin_unlock_irqrestore(&info->lock, flags);
 
        dbg ("%s - returns %d", __FUNCTION__, chars);
-       return (chars);
+       return chars;
 }
 
 
@@ -962,54 +963,57 @@ static void whiteheat_unthrottle (struct usb_serial_port *port)
 /*****************************************************************************
  * Connect Tech's White Heat callback routines
  *****************************************************************************/
-static void command_port_write_callback (struct urb *urb)
+static void command_port_write_callback(struct urb *urb)
 {
+       int status = urb->status;
+
        dbg("%s", __FUNCTION__);
 
-       if (urb->status) {
-               dbg ("nonzero urb status: %d", urb->status);
+       if (status) {
+               dbg("nonzero urb status: %d", status);
                return;
        }
 }
 
 
-static void command_port_read_callback (struct urb *urb)
+static void command_port_read_callback(struct urb *urb)
 {
        struct usb_serial_port *command_port = (struct usb_serial_port *)urb->context;
        struct whiteheat_command_private *command_info;
+       int status = urb->status;
        unsigned char *data = urb->transfer_buffer;
        int result;
-       unsigned long flags;
 
        dbg("%s", __FUNCTION__);
 
-       if (urb->status) {
-               dbg("%s - nonzero urb status: %d", __FUNCTION__, urb->status);
-               return;
-       }
-
-       usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data);
-
        command_info = usb_get_serial_port_data(command_port);
        if (!command_info) {
                dbg ("%s - command_info is NULL, exiting.", __FUNCTION__);
                return;
        }
-       spin_lock_irqsave(&command_info->lock, flags);
+       if (status) {
+               dbg("%s - nonzero urb status: %d", __FUNCTION__, status);
+               if (status != -ENOENT)
+                       command_info->command_finished = WHITEHEAT_CMD_FAILURE;
+               wake_up(&command_info->wait_command);
+               return;
+       }
+
+       usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data);
 
        if (data[0] == WHITEHEAT_CMD_COMPLETE) {
                command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
-               wake_up_interruptible(&command_info->wait_command);
+               wake_up(&command_info->wait_command);
        } else if (data[0] == WHITEHEAT_CMD_FAILURE) {
                command_info->command_finished = WHITEHEAT_CMD_FAILURE;
-               wake_up_interruptible(&command_info->wait_command);
+               wake_up(&command_info->wait_command);
        } else if (data[0] == WHITEHEAT_EVENT) {
                /* These are unsolicited reports from the firmware, hence no waiting command to wakeup */
                dbg("%s - event received", __FUNCTION__);
        } else if (data[0] == WHITEHEAT_GET_DTR_RTS) {
                memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1);
                command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
-               wake_up_interruptible(&command_info->wait_command);
+               wake_up(&command_info->wait_command);
        } else {
                dbg("%s - bad reply from firmware", __FUNCTION__);
        }
@@ -1017,7 +1021,6 @@ static void command_port_read_callback (struct urb *urb)
        /* Continue trying to always read */
        command_port->read_urb->dev = command_port->serial->dev;
        result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC);
-       spin_unlock_irqrestore(&command_info->lock, flags);
        if (result)
                dbg("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
 }
@@ -1029,6 +1032,7 @@ static void whiteheat_read_callback(struct urb *urb)
        struct whiteheat_urb_wrap *wrap;
        unsigned char *data = urb->transfer_buffer;
        struct whiteheat_private *info = usb_get_serial_port_data(port);
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -1042,8 +1046,9 @@ static void whiteheat_read_callback(struct urb *urb)
        list_del(&wrap->list);
        spin_unlock(&info->lock);
 
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __FUNCTION__, status);
                spin_lock(&info->lock);
                list_add(&wrap->list, &info->rx_urbs_free);
                spin_unlock(&info->lock);
@@ -1070,6 +1075,7 @@ static void whiteheat_write_callback(struct urb *urb)
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct whiteheat_private *info = usb_get_serial_port_data(port);
        struct whiteheat_urb_wrap *wrap;
+       int status = urb->status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -1083,8 +1089,9 @@ static void whiteheat_write_callback(struct urb *urb)
        list_move(&wrap->list, &info->tx_urbs_free);
        spin_unlock(&info->lock);
 
-       if (urb->status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, status);
                return;
        }
 
@@ -1095,20 +1102,20 @@ static void whiteheat_write_callback(struct urb *urb)
 /*****************************************************************************
  * Connect Tech's White Heat firmware interface
  *****************************************************************************/
-static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize)
+static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize)
 {
        struct usb_serial_port *command_port;
        struct whiteheat_command_private *command_info;
        struct whiteheat_private *info;
        __u8 *transfer_buffer;
        int retval = 0;
-       unsigned long flags;
+       int t;
 
        dbg("%s - command %d", __FUNCTION__, command);
 
        command_port = port->serial->port[COMMAND_PORT];
        command_info = usb_get_serial_port_data(command_port);
-       spin_lock_irqsave(&command_info->lock, flags);
+       mutex_lock(&command_info->mutex);
        command_info->command_finished = false;
        
        transfer_buffer = (__u8 *)command_port->write_urb->transfer_buffer;
@@ -1116,18 +1123,17 @@ static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *
        memcpy (&transfer_buffer[1], data, datasize);
        command_port->write_urb->transfer_buffer_length = datasize + 1;
        command_port->write_urb->dev = port->serial->dev;
-       retval = usb_submit_urb (command_port->write_urb, GFP_KERNEL);
+       retval = usb_submit_urb (command_port->write_urb, GFP_NOIO);
        if (retval) {
                dbg("%s - submit urb failed", __FUNCTION__);
                goto exit;
        }
-       spin_unlock_irqrestore(&command_info->lock, flags);
 
        /* wait for the command to complete */
-       wait_event_interruptible_timeout(command_info->wait_command,
+       t = wait_event_timeout(command_info->wait_command,
                (bool)command_info->command_finished, COMMAND_TIMEOUT);
-
-       spin_lock_irqsave(&command_info->lock, flags);
+       if (!t)
+               usb_kill_urb(command_port->write_urb);
 
        if (command_info->command_finished == false) {
                dbg("%s - command timed out.", __FUNCTION__);
@@ -1152,7 +1158,7 @@ static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *
        }
 
 exit:
-       spin_unlock_irqrestore(&command_info->lock, flags);
+       mutex_unlock(&command_info->mutex);
        return retval;
 }
 
@@ -1305,12 +1311,11 @@ static int start_command_port(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
        struct whiteheat_command_private *command_info;
-       unsigned long flags;
        int retval = 0;
        
        command_port = serial->port[COMMAND_PORT];
        command_info = usb_get_serial_port_data(command_port);
-       spin_lock_irqsave(&command_info->lock, flags);
+       mutex_lock(&command_info->mutex);
        if (!command_info->port_running) {
                /* Work around HCD bugs */
                usb_clear_halt(serial->dev, command_port->read_urb->pipe);
@@ -1325,7 +1330,7 @@ static int start_command_port(struct usb_serial *serial)
        command_info->port_running++;
 
 exit:
-       spin_unlock_irqrestore(&command_info->lock, flags);
+       mutex_unlock(&command_info->mutex);
        return retval;
 }
 
@@ -1334,15 +1339,14 @@ static void stop_command_port(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
        struct whiteheat_command_private *command_info;
-       unsigned long flags;
 
        command_port = serial->port[COMMAND_PORT];
        command_info = usb_get_serial_port_data(command_port);
-       spin_lock_irqsave(&command_info->lock, flags);
+       mutex_lock(&command_info->mutex);
        command_info->port_running--;
        if (!command_info->port_running)
                usb_kill_urb(command_port->read_urb);
-       spin_unlock_irqrestore(&command_info->lock, flags);
+       mutex_unlock(&command_info->mutex);
 }
 
 
@@ -1363,17 +1367,23 @@ static int start_port_read(struct usb_serial_port *port)
                wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
                urb = wrap->urb;
                urb->dev = port->serial->dev;
+               spin_unlock_irqrestore(&info->lock, flags);
                retval = usb_submit_urb(urb, GFP_KERNEL);
                if (retval) {
+                       spin_lock_irqsave(&info->lock, flags);
                        list_add(tmp, &info->rx_urbs_free);
                        list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
                                wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
                                urb = wrap->urb;
+                               list_del(tmp);
+                               spin_unlock_irqrestore(&info->lock, flags);
                                usb_kill_urb(urb);
-                               list_move(tmp, &info->rx_urbs_free);
+                               spin_lock_irqsave(&info->lock, flags);
+                               list_add(tmp, &info->rx_urbs_free);
                        }
                        break;
                }
+               spin_lock_irqsave(&info->lock, flags);
                list_add(tmp, &info->rx_urbs_submitted);
        }
 
index e227f64d5641be64dc009c34da147be8c0a61a69..47e56079925dfbf8d222024c9cca704ce9ff21e2 100644 (file)
@@ -285,10 +285,15 @@ static int device_reset(struct scsi_cmnd *srb)
 
        US_DEBUGP("%s called\n", __FUNCTION__);
 
-       /* lock the device pointers and do the reset */
-       mutex_lock(&(us->dev_mutex));
-       result = us->transport_reset(us);
-       mutex_unlock(&us->dev_mutex);
+       result = usb_autopm_get_interface(us->pusb_intf);
+       if (result == 0) {
+
+               /* lock the device pointers and do the reset */
+               mutex_lock(&(us->dev_mutex));
+               result = us->transport_reset(us);
+               mutex_unlock(&us->dev_mutex);
+               usb_autopm_put_interface(us->pusb_intf);
+       }
 
        return result < 0 ? FAILED : SUCCESS;
 }
@@ -321,10 +326,14 @@ void usb_stor_report_device_reset(struct us_data *us)
 
 /* Report a driver-initiated bus reset to the SCSI layer.
  * Calling this for a SCSI-initiated reset is unnecessary but harmless.
- * The caller must own the SCSI host lock. */
+ * The caller must not own the SCSI host lock. */
 void usb_stor_report_bus_reset(struct us_data *us)
 {
-       scsi_report_bus_reset(us_to_host(us), 0);
+       struct Scsi_Host *host = us_to_host(us);
+
+       scsi_lock(host);
+       scsi_report_bus_reset(host, 0);
+       scsi_unlock(host);
 }
 
 /***********************************************************************
index 54979c239c6329d7382176e7996a5384c371b160..b6bf31a97b60d46bff07725cc7eec98b1a5e7c65 100644 (file)
 /* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr>
  */
 UNUSUAL_DEV(  0x03eb, 0x2002, 0x0100, 0x0100,
-                "ATMEL",
-                "SND1 Storage",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_IGNORE_RESIDUE),
+               "ATMEL",
+               "SND1 Storage",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_IGNORE_RESIDUE),
 
 /* modified by Tobias Lorenz <tobias.lorenz@gmx.net> */
 UNUSUAL_DEV(  0x03ee, 0x6901, 0x0000, 0x0200,
@@ -69,18 +69,18 @@ UNUSUAL_DEV(  0x03ee, 0x6906, 0x0003, 0x0003,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_IGNORE_RESIDUE ),
 
-UNUSUAL_DEV(  0x03f0, 0x0107, 0x0200, 0x0200, 
+UNUSUAL_DEV(  0x03f0, 0x0107, 0x0200, 0x0200,
                "HP",
                "CD-Writer+",
-               US_SC_8070, US_PR_CB, NULL, 0), 
+               US_SC_8070, US_PR_CB, NULL, 0),
 
 #ifdef CONFIG_USB_STORAGE_USBAT
-UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001, 
+UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001,
                "HP",
                "CD-Writer+ 8200e",
                US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
 
-UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001, 
+UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001,
                "HP",
                "CD-Writer+ CD-4e",
                US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
@@ -115,10 +115,10 @@ UNUSUAL_DEV(  0x0411, 0x001c, 0x0113, 0x0113,
 
 /* Submitted by Ernestas Vaiciukevicius <ernisv@gmail.com> */
 UNUSUAL_DEV(  0x0419, 0x0100, 0x0100, 0x0100,
-                "Samsung Info. Systems America, Inc.",
-                "MP3 Player",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_IGNORE_RESIDUE ),
+               "Samsung Info. Systems America, Inc.",
+               "MP3 Player",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Orgad Shaneh <orgads@gmail.com> */
 UNUSUAL_DEV(  0x0419, 0xaace, 0x0100, 0x0100,
@@ -256,10 +256,10 @@ UNUSUAL_DEV(  0x0457, 0x0150, 0x0100, 0x0100,
 * the revision to my model only
 */
 UNUSUAL_DEV(  0x0457, 0x0151, 0x0100, 0x0100,
-                "USB 2.0",
-                "Flash Disk",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_NOT_LOCKABLE ),
+               "USB 2.0",
+               "Flash Disk",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_NOT_LOCKABLE ),
 
 #ifdef CONFIG_USB_STORAGE_KARMA
 UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
@@ -408,19 +408,19 @@ UNUSUAL_DEV(  0x04da, 0x2373, 0x0000, 0x9999,
 /* Most of the following entries were developed with the help of
  * Shuttle/SCM directly.
  */
-UNUSUAL_DEV(  0x04e6, 0x0001, 0x0200, 0x0200, 
+UNUSUAL_DEV(  0x04e6, 0x0001, 0x0200, 0x0200,
                "Matshita",
                "LS-120",
                US_SC_8020, US_PR_CB, NULL, 0),
 
-UNUSUAL_DEV(  0x04e6, 0x0002, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x04e6, 0x0002, 0x0100, 0x0100,
                "Shuttle",
                "eUSCSI Bridge",
                US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, 
-               US_FL_SCM_MULT_TARG ), 
+               US_FL_SCM_MULT_TARG ),
 
 #ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999, 
+UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999,
                "Sandisk",
                "ImageMate SDDR09",
                US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
@@ -431,52 +431,52 @@ UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
                "SCM Microsystems",
                "eUSB SmartMedia / CompactFlash Adapter",
                US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
-               0), 
+               0),
 #endif
 
 /* Reported by Markus Demleitner <msdemlei@cl.uni-heidelberg.de> */
-UNUSUAL_DEV(  0x04e6, 0x0006, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x04e6, 0x0006, 0x0100, 0x0100,
                "SCM Microsystems Inc.",
                "eUSB MMC Adapter",
-               US_SC_SCSI, US_PR_CB, NULL, 
-               US_FL_SINGLE_LUN), 
+               US_SC_SCSI, US_PR_CB, NULL,
+               US_FL_SINGLE_LUN),
 
 /* Reported by Daniel Nouri <dpunktnpunkt@web.de> */
-UNUSUAL_DEV(  0x04e6, 0x0006, 0x0205, 0x0205, 
+UNUSUAL_DEV(  0x04e6, 0x0006, 0x0205, 0x0205,
                "Shuttle",
                "eUSB MMC Adapter",
-               US_SC_SCSI, US_PR_DEVICE, NULL, 
-               US_FL_SINGLE_LUN), 
+               US_SC_SCSI, US_PR_DEVICE, NULL,
+               US_FL_SINGLE_LUN),
 
-UNUSUAL_DEV(  0x04e6, 0x0007, 0x0100, 0x0200, 
+UNUSUAL_DEV(  0x04e6, 0x0007, 0x0100, 0x0200,
                "Sony",
                "Hifd",
-               US_SC_SCSI, US_PR_CB, NULL, 
-               US_FL_SINGLE_LUN), 
+               US_SC_SCSI, US_PR_CB, NULL,
+               US_FL_SINGLE_LUN),
 
-UNUSUAL_DEV(  0x04e6, 0x0009, 0x0200, 0x0200, 
+UNUSUAL_DEV(  0x04e6, 0x0009, 0x0200, 0x0200,
                "Shuttle",
                "eUSB ATA/ATAPI Adapter",
                US_SC_8020, US_PR_CB, NULL, 0),
 
-UNUSUAL_DEV(  0x04e6, 0x000a, 0x0200, 0x0200, 
+UNUSUAL_DEV(  0x04e6, 0x000a, 0x0200, 0x0200,
                "Shuttle",
                "eUSB CompactFlash Adapter",
                US_SC_8020, US_PR_CB, NULL, 0),
 
-UNUSUAL_DEV(  0x04e6, 0x000B, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x04e6, 0x000B, 0x0100, 0x0100,
                "Shuttle",
                "eUSCSI Bridge",
-               US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
+               US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
                US_FL_SCM_MULT_TARG ), 
 
-UNUSUAL_DEV(  0x04e6, 0x000C, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x04e6, 0x000C, 0x0100, 0x0100,
                "Shuttle",
                "eUSCSI Bridge",
-               US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
-               US_FL_SCM_MULT_TARG ), 
+               US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+               US_FL_SCM_MULT_TARG ),
 
-UNUSUAL_DEV(  0x04e6, 0x0101, 0x0200, 0x0200, 
+UNUSUAL_DEV(  0x04e6, 0x0101, 0x0200, 0x0200,
                "Shuttle",
                "CD-RW Device",
                US_SC_8020, US_PR_CB, NULL, 0),
@@ -556,9 +556,9 @@ UNUSUAL_DEV(  0x052b, 0x1911, 0x0100, 0x0100,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_IGNORE_RESIDUE ),
 
-UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0450, 
+UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0450,
                "Sony",
-               "DSC-S30/S70/S75/505V/F505/F707/F717/P8", 
+               "DSC-S30/S70/S75/505V/F505/F707/F717/P8",
                US_SC_SCSI, US_PR_DEVICE, NULL,
                US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
 
@@ -572,7 +572,7 @@ UNUSUAL_DEV(  0x054c, 0x0010, 0x0500, 0x0610,
 
 
 /* Reported by wim@geeks.nl */
-UNUSUAL_DEV(  0x054c, 0x0025, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x054c, 0x0025, 0x0100, 0x0100,
                "Sony",
                "Memorystick NW-MS7",
                US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -593,21 +593,21 @@ UNUSUAL_DEV(  0x054c, 0x002c, 0x0501, 0x2000,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_SINGLE_LUN ),
 
-UNUSUAL_DEV(  0x054c, 0x002d, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x054c, 0x002d, 0x0100, 0x0100,
                "Sony",
                "Memorystick MSAC-US1",
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_SINGLE_LUN ),
 
 /* Submitted by Klaus Mueller <k.mueller@intershop.de> */
-UNUSUAL_DEV(  0x054c, 0x002e, 0x0106, 0x0310, 
+UNUSUAL_DEV(  0x054c, 0x002e, 0x0106, 0x0310,
                "Sony",
                "Handycam",
                US_SC_SCSI, US_PR_DEVICE, NULL,
                US_FL_SINGLE_LUN ),
 
 /* Submitted by Rajesh Kumble Nayak <nayak@obs-nice.fr> */
-UNUSUAL_DEV(  0x054c, 0x002e, 0x0500, 0x0500, 
+UNUSUAL_DEV(  0x054c, 0x002e, 0x0500, 0x0500,
                "Sony",
                "Handycam HC-85",
                US_SC_UFI, US_PR_DEVICE, NULL,
@@ -648,26 +648,26 @@ UNUSUAL_DEV(  0x054c, 0x016a, 0x0000, 0x9999,
                
 /* Submitted by Frank Engel <frankie@cse.unsw.edu.au> */
 UNUSUAL_DEV(  0x054c, 0x0099, 0x0000, 0x9999,
-                "Sony",
-                "PEG Mass Storage",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_FIX_INQUIRY ),
+               "Sony",
+               "PEG Mass Storage",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_INQUIRY ),
 
 /* floppy reports multiple luns */
 UNUSUAL_DEV(  0x055d, 0x2020, 0x0000, 0x0210,
-               "SAMSUNG",
-               "SFD-321U [FW 0C]",
-               US_SC_DEVICE, US_PR_DEVICE, NULL,
-               US_FL_SINGLE_LUN ),
+               "SAMSUNG",
+               "SFD-321U [FW 0C]",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_SINGLE_LUN ),
 
                
-UNUSUAL_DEV(  0x057b, 0x0000, 0x0000, 0x0299, 
+UNUSUAL_DEV(  0x057b, 0x0000, 0x0000, 0x0299,
                "Y-E Data",
                "Flashbuster-U",
                US_SC_DEVICE,  US_PR_CB, NULL,
                US_FL_SINGLE_LUN),
 
-UNUSUAL_DEV(  0x057b, 0x0000, 0x0300, 0x9999, 
+UNUSUAL_DEV(  0x057b, 0x0000, 0x0300, 0x9999,
                "Y-E Data",
                "Flashbuster-U",
                US_SC_DEVICE,  US_PR_DEVICE, NULL,
@@ -677,7 +677,7 @@ UNUSUAL_DEV(  0x057b, 0x0000, 0x0300, 0x9999,
  * This entry is needed only because the device reports
  * bInterfaceClass = 0xff (vendor-specific)
  */
-UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999, 
+UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999,
                "Y-E Data",
                "Silicon Media R/W",
                US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
@@ -825,13 +825,13 @@ UNUSUAL_DEV(  0x0636, 0x0003, 0x0000, 0x9999,
                US_SC_SCSI, US_PR_BULK, NULL,
                US_FL_FIX_INQUIRY ),
 
-UNUSUAL_DEV(  0x0644, 0x0000, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x0644, 0x0000, 0x0100, 0x0100,
                "TEAC",
                "Floppy Drive",
-               US_SC_UFI, US_PR_CB, NULL, 0 ), 
+               US_SC_UFI, US_PR_CB, NULL, 0 ),
 
 #ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100,
                "Olympus",
                "Camedia MAUSB-2",
                US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
@@ -867,14 +867,14 @@ UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
 
 /* Reported by Miguel A. Fosas <amn3s1a@ono.com> */
 UNUSUAL_DEV(  0x0686, 0x4017, 0x0001, 0x0001,
-                "Minolta",
-                "DIMAGE E223",
-                US_SC_SCSI, US_PR_DEVICE, NULL, 0 ),
+               "Minolta",
+               "DIMAGE E223",
+               US_SC_SCSI, US_PR_DEVICE, NULL, 0 ),
 
 UNUSUAL_DEV(  0x0693, 0x0005, 0x0100, 0x0100,
                "Hagiwara",
                "Flashgate",
-               US_SC_SCSI, US_PR_BULK, NULL, 0 ), 
+               US_SC_SCSI, US_PR_BULK, NULL, 0 ),
 
 /* Reported by David Hamilton <niftimusmaximus@lycos.com> */
 UNUSUAL_DEV(  0x069b, 0x3004, 0x0001, 0x0001,
@@ -918,7 +918,7 @@ UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
                US_FL_SINGLE_LUN ),
 
 #ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999, 
+UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999,
                "Sandisk",
                "ImageMate SDDR-09",
                US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
@@ -939,17 +939,17 @@ UNUSUAL_DEV(  0x07ab, 0xfccd, 0x0000, 0x9999,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY),
 
-UNUSUAL_DEV(  0x07af, 0x0004, 0x0100, 0x0133, 
+UNUSUAL_DEV(  0x07af, 0x0004, 0x0100, 0x0133,
                "Microtech",
                "USB-SCSI-DB25",
                US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
                US_FL_SCM_MULT_TARG ), 
 
-UNUSUAL_DEV(  0x07af, 0x0005, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x07af, 0x0005, 0x0100, 0x0100,
                "Microtech",
                "USB-SCSI-HD50",
                US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
-               US_FL_SCM_MULT_TARG ), 
+               US_FL_SCM_MULT_TARG ),
 
 #ifdef CONFIG_USB_STORAGE_DPCM
 UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
@@ -1053,10 +1053,10 @@ UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
  * as "DualSlot CompactFlash(TM) & MStick Drive USB"
  */
 UNUSUAL_DEV(  0x07c4, 0xa10b, 0x0000, 0xffff,
-                "DataFab Systems Inc.",
-                "USB CF+MS",
-                US_SC_SCSI, US_PR_DATAFAB, NULL,
-                0 ),
+               "DataFab Systems Inc.",
+               "USB CF+MS",
+               US_SC_SCSI, US_PR_DATAFAB, NULL,
+               0 ),
 
 #endif
 
@@ -1119,10 +1119,10 @@ UNUSUAL_DEV(  0x08bd, 0x1100, 0x0000, 0x0000,
  * US_FL_IGNORE_RESIDUE Needed
  */
 UNUSUAL_DEV(  0x08ca, 0x3103, 0x0100, 0x0100,
-                "AIPTEK",
-                "Aiptek USB Keychain MP3 Player",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_IGNORE_RESIDUE),
+               "AIPTEK",
+               "Aiptek USB Keychain MP3 Player",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_IGNORE_RESIDUE),
 
 /* Entry needed for flags. Moreover, all devices with this ID use
  * bulk-only transport, but _some_ falsely report Control/Bulk instead.
@@ -1166,26 +1166,26 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
  * Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
  */
 UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
-                "Pentax",
-                "Optio 2/3/400",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_FIX_INQUIRY ),
+               "Pentax",
+               "Optio 2/3/400",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_INQUIRY ),
 
 
 /* Submitted by Per Winkvist <per.winkvist@uk.com> */
 UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff,
-                "Pentax",
-                "Optio S/S4",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_FIX_INQUIRY ),
+               "Pentax",
+               "Optio S/S4",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_INQUIRY ),
 
 /* These are virtual windows driver CDs, which the zd1211rw driver
  * automatically converts into WLAN devices. */
 UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101,
-                "ZyXEL",
-                "G-220F USB-WLAN Install",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_IGNORE_DEVICE ),
+               "ZyXEL",
+               "G-220F USB-WLAN Install",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_IGNORE_DEVICE ),
 
 UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101,
                "SiteCom",
@@ -1211,17 +1211,17 @@ UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x0110,
 
 #ifdef CONFIG_USB_STORAGE_DATAFAB
 UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
-              "Acomdata",
-              "CF",
-              US_SC_SCSI, US_PR_DATAFAB, NULL,
-              US_FL_SINGLE_LUN ),
+               "Acomdata",
+               "CF",
+               US_SC_SCSI, US_PR_DATAFAB, NULL,
+               US_FL_SINGLE_LUN ),
 #endif
 #ifdef CONFIG_USB_STORAGE_SDDR55
 UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
-              "Acomdata",
-              "SM",
-              US_SC_SCSI, US_PR_SDDR55, NULL,
-              US_FL_SINGLE_LUN ),
+               "Acomdata",
+               "SM",
+               US_SC_SCSI, US_PR_SDDR55, NULL,
+               US_FL_SINGLE_LUN ),
 #endif
 
 /* Submitted by: Nick Sillik <n.sillik@temple.edu>
index 8e898e3d861ea477153ce8f782230ede58e1292f..bef8bcd9bd9824fa428c6108a1010d6c2e5e479b 100644 (file)
@@ -191,16 +191,13 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
+       US_DEBUGP("%s\n", __FUNCTION__);
+
        /* Wait until no command is running */
        mutex_lock(&us->dev_mutex);
 
-       US_DEBUGP("%s\n", __FUNCTION__);
        if (us->suspend_resume_hook)
                (us->suspend_resume_hook)(us, US_SUSPEND);
-       iface->dev.power.power_state.event = message.event;
-
-       /* When runtime PM is working, we'll set a flag to indicate
-        * whether we should autoresume when a SCSI request arrives. */
 
        mutex_unlock(&us->dev_mutex);
        return 0;
@@ -210,14 +207,25 @@ static int storage_resume(struct usb_interface *iface)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
-       mutex_lock(&us->dev_mutex);
-
        US_DEBUGP("%s\n", __FUNCTION__);
+
        if (us->suspend_resume_hook)
                (us->suspend_resume_hook)(us, US_RESUME);
-       iface->dev.power.power_state.event = PM_EVENT_ON;
 
-       mutex_unlock(&us->dev_mutex);
+       return 0;
+}
+
+static int storage_reset_resume(struct usb_interface *iface)
+{
+       struct us_data *us = usb_get_intfdata(iface);
+
+       US_DEBUGP("%s\n", __FUNCTION__);
+
+       /* Report the reset to the SCSI core */
+       usb_stor_report_bus_reset(us);
+
+       /* FIXME: Notify the subdrivers that they need to reinitialize
+        * the device */
        return 0;
 }
 
@@ -228,7 +236,7 @@ static int storage_resume(struct usb_interface *iface)
  * a USB port reset, whether from this driver or a different one.
  */
 
-static void storage_pre_reset(struct usb_interface *iface)
+static int storage_pre_reset(struct usb_interface *iface)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
@@ -236,22 +244,23 @@ static void storage_pre_reset(struct usb_interface *iface)
 
        /* Make sure no command runs during the reset */
        mutex_lock(&us->dev_mutex);
+       return 0;
 }
 
-static void storage_post_reset(struct usb_interface *iface)
+static int storage_post_reset(struct usb_interface *iface)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
        US_DEBUGP("%s\n", __FUNCTION__);
 
        /* Report the reset to the SCSI core */
-       scsi_lock(us_to_host(us));
        usb_stor_report_bus_reset(us);
-       scsi_unlock(us_to_host(us));
 
        /* FIXME: Notify the subdrivers that they need to reinitialize
         * the device */
+
        mutex_unlock(&us->dev_mutex);
+       return 0;
 }
 
 /*
@@ -300,6 +309,7 @@ static int usb_stor_control_thread(void * __us)
 {
        struct us_data *us = (struct us_data *)__us;
        struct Scsi_Host *host = us_to_host(us);
+       int autopm_rc;
 
        current->flags |= PF_NOFREEZE;
 
@@ -310,6 +320,9 @@ static int usb_stor_control_thread(void * __us)
                        
                US_DEBUGP("*** thread awakened.\n");
 
+               /* Autoresume the device */
+               autopm_rc = usb_autopm_get_interface(us->pusb_intf);
+
                /* lock the device pointers */
                mutex_lock(&(us->dev_mutex));
 
@@ -368,6 +381,12 @@ static int usb_stor_control_thread(void * __us)
                        us->srb->result = SAM_STAT_GOOD;
                }
 
+               /* Did the autoresume fail? */
+               else if (autopm_rc < 0) {
+                       US_DEBUGP("Could not wake device\n");
+                       us->srb->result = DID_ERROR << 16;
+               }
+
                /* we've got a command, let's do it! */
                else {
                        US_DEBUG(usb_stor_show_command(us->srb));
@@ -410,25 +429,21 @@ SkipForAbort:
 
                /* unlock the device pointers */
                mutex_unlock(&us->dev_mutex);
-       } /* for (;;) */
 
-       scsi_host_put(host);
+               /* Start an autosuspend */
+               if (autopm_rc == 0)
+                       usb_autopm_put_interface(us->pusb_intf);
+       } /* for (;;) */
 
-       /* notify the exit routine that we're actually exiting now 
-        *
-        * complete()/wait_for_completion() is similar to up()/down(),
-        * except that complete() is safe in the case where the structure
-        * is getting deleted in a parallel mode of execution (i.e. just
-        * after the down() -- that's necessary for the thread-shutdown
-        * case.
-        *
-        * complete_and_exit() goes even further than this -- it is safe in
-        * the case that the thread of the caller is going away (not just
-        * the structure) -- this is necessary for the module-remove case.
-        * This is important in preemption kernels, which transfer the flow
-        * of execution immediately upon a complete().
-        */
-       complete_and_exit(&threads_gone, 0);
+       /* Wait until we are told to stop */
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (kthread_should_stop())
+                       break;
+               schedule();
+       }
+       __set_current_state(TASK_RUNNING);
+       return 0;
 }      
 
 /***********************************************************************
@@ -796,19 +811,13 @@ static int usb_stor_acquire_resources(struct us_data *us)
        }
 
        /* Start up our control thread */
-       th = kthread_create(usb_stor_control_thread, us, "usb-storage");
+       th = kthread_run(usb_stor_control_thread, us, "usb-storage");
        if (IS_ERR(th)) {
                printk(KERN_WARNING USB_STORAGE 
                       "Unable to start control thread\n");
                return PTR_ERR(th);
        }
-
-       /* Take a reference to the host for the control thread and
-        * count it among all the threads we have launched.  Then
-        * start it up. */
-       scsi_host_get(us_to_host(us));
-       atomic_inc(&total_threads);
-       wake_up_process(th);
+       us->ctl_thread = th;
 
        return 0;
 }
@@ -825,6 +834,8 @@ static void usb_stor_release_resources(struct us_data *us)
        US_DEBUGP("-- sending exit command to thread\n");
        set_bit(US_FLIDX_DISCONNECTING, &us->flags);
        up(&us->sema);
+       if (us->ctl_thread)
+               kthread_stop(us->ctl_thread);
 
        /* Call the destructor routine, if it exists */
        if (us->extra_destructor) {
@@ -938,6 +949,7 @@ retry:
        }
 
        scsi_host_put(us_to_host(us));
+       usb_autopm_put_interface(us->pusb_intf);
        complete_and_exit(&threads_gone, 0);
 }
 
@@ -1027,6 +1039,7 @@ static int storage_probe(struct usb_interface *intf,
         * start it up. */
        scsi_host_get(us_to_host(us));
        atomic_inc(&total_threads);
+       usb_autopm_get_interface(intf); /* dropped in the scanning thread */
        wake_up_process(th);
 
        return 0;
@@ -1059,10 +1072,12 @@ static struct usb_driver usb_storage_driver = {
 #ifdef CONFIG_PM
        .suspend =      storage_suspend,
        .resume =       storage_resume,
+       .reset_resume = storage_reset_resume,
 #endif
        .pre_reset =    storage_pre_reset,
        .post_reset =   storage_post_reset,
        .id_table =     storage_usb_ids,
+       .supports_autosuspend = 1,
 };
 
 static int __init usb_stor_init(void)
index 6dac1ffdde86203ed6972679e0432848d47521d3..6445665b1577c258d3a722e19e9a56fac549267a 100644 (file)
@@ -144,6 +144,7 @@ struct us_data {
        unsigned char           *sensebuf;       /* sense data buffer    */
        dma_addr_t              cr_dma;          /* buffer DMA addresses */
        dma_addr_t              iobuf_dma;
+       struct task_struct      *ctl_thread;     /* the control thread   */
 
        /* mutual exclusion and synchronization structures */
        struct semaphore        sema;            /* to sleep thread on      */
index 8432bf171d2e8468a6e608e550152bcb25cd76bf..8de11deb5d1429dffb16febcd1d834623b59d0c5 100644 (file)
@@ -34,9 +34,6 @@ static struct usb_device_id skel_table [] = {
 };
 MODULE_DEVICE_TABLE(usb, skel_table);
 
-/* to prevent a race between open and disconnect */
-static DEFINE_MUTEX(skel_open_lock);
-
 
 /* Get a minor range for your devices from the usb maintainer */
 #define USB_SKEL_MINOR_BASE    192
@@ -54,16 +51,21 @@ struct usb_skel {
        struct usb_device       *udev;                  /* the usb device for this device */
        struct usb_interface    *interface;             /* the interface for this device */
        struct semaphore        limit_sem;              /* limiting the number of writes in progress */
+       struct usb_anchor       submitted;              /* in case we need to retract our submissions */
        unsigned char           *bulk_in_buffer;        /* the buffer to receive data */
        size_t                  bulk_in_size;           /* the size of the receive buffer */
        __u8                    bulk_in_endpointAddr;   /* the address of the bulk in endpoint */
        __u8                    bulk_out_endpointAddr;  /* the address of the bulk out endpoint */
+       int                     errors;                 /* the last request tanked */
+       int                     open_count;             /* count the number of openers */
+       spinlock_t              err_lock;               /* lock for errors */
        struct kref             kref;
        struct mutex            io_mutex;               /* synchronize I/O with disconnect */
 };
 #define to_skel_dev(d) container_of(d, struct usb_skel, kref)
 
 static struct usb_driver skel_driver;
+static void skel_draw_down(struct usb_skel *dev);
 
 static void skel_delete(struct kref *kref)
 {
@@ -83,10 +85,8 @@ static int skel_open(struct inode *inode, struct file *file)
 
        subminor = iminor(inode);
 
-       mutex_lock(&skel_open_lock);
        interface = usb_find_interface(&skel_driver, subminor);
        if (!interface) {
-               mutex_unlock(&skel_open_lock);
                err ("%s - error, can't find device for minor %d",
                     __FUNCTION__, subminor);
                retval = -ENODEV;
@@ -95,22 +95,33 @@ static int skel_open(struct inode *inode, struct file *file)
 
        dev = usb_get_intfdata(interface);
        if (!dev) {
-               mutex_unlock(&skel_open_lock);
                retval = -ENODEV;
                goto exit;
        }
 
        /* increment our usage count for the device */
        kref_get(&dev->kref);
-       /* now we can drop the lock */
-       mutex_unlock(&skel_open_lock);
 
-       /* prevent the device from being autosuspended */
-       retval = usb_autopm_get_interface(interface);
-       if (retval) {
+       /* lock the device to allow correctly handling errors
+        * in resumption */
+       mutex_lock(&dev->io_mutex);
+
+       if (!dev->open_count++) {
+               retval = usb_autopm_get_interface(interface);
+                       if (retval) {
+                               dev->open_count--;
+                               mutex_unlock(&dev->io_mutex);
+                               kref_put(&dev->kref, skel_delete);
+                               goto exit;
+                       }
+       } /* else { //uncomment this block if you want exclusive open
+               retval = -EBUSY;
+               dev->open_count--;
+               mutex_unlock(&dev->io_mutex);
                kref_put(&dev->kref, skel_delete);
                goto exit;
-       }
+       } */
+       /* prevent the device from being autosuspended */
 
        /* save our object in the file's private structure */
        file->private_data = dev;
@@ -129,7 +140,7 @@ static int skel_release(struct inode *inode, struct file *file)
 
        /* allow the device to be autosuspended */
        mutex_lock(&dev->io_mutex);
-       if (dev->interface)
+       if (!--dev->open_count && dev->interface)
                usb_autopm_put_interface(dev->interface);
        mutex_unlock(&dev->io_mutex);
 
@@ -138,6 +149,30 @@ static int skel_release(struct inode *inode, struct file *file)
        return 0;
 }
 
+static int skel_flush(struct file *file, fl_owner_t id)
+{
+       struct usb_skel *dev;
+       int res;
+
+       dev = (struct usb_skel *)file->private_data;
+       if (dev == NULL)
+               return -ENODEV;
+
+       /* wait for io to stop */
+       mutex_lock(&dev->io_mutex);
+       skel_draw_down(dev);
+
+       /* read out errors, leave subsequent opens a clean slate */
+       spin_lock_irq(&dev->err_lock);
+       res = dev->errors ? (dev->errors == -EPIPE ? -EPIPE : -EIO) : 0;
+       dev->errors = 0;
+       spin_unlock_irq(&dev->err_lock);
+
+       mutex_unlock(&dev->io_mutex);
+
+       return res;
+}
+
 static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
        struct usb_skel *dev;
@@ -179,12 +214,16 @@ static void skel_write_bulk_callback(struct urb *urb)
        dev = (struct usb_skel *)urb->context;
 
        /* sync/async unlink faults aren't errors */
-       if (urb->status &&
-           !(urb->status == -ENOENT ||
-             urb->status == -ECONNRESET ||
-             urb->status == -ESHUTDOWN)) {
-               err("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, urb->status);
+       if (urb->status) {
+               if(!(urb->status == -ENOENT ||
+                   urb->status == -ECONNRESET ||
+                   urb->status == -ESHUTDOWN))
+                       err("%s - nonzero write bulk status received: %d",
+                           __FUNCTION__, urb->status);
+
+               spin_lock(&dev->err_lock);
+               dev->errors = urb->status;
+               spin_unlock(&dev->err_lock);
        }
 
        /* free up our allocated buffer */
@@ -213,6 +252,17 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
                goto exit;
        }
 
+       spin_lock_irq(&dev->err_lock);
+       if ((retval = dev->errors) < 0) {
+               /* any error is reported once */
+               dev->errors = 0;
+               /* to preserve notifications about reset */
+               retval = (retval == -EPIPE) ? retval : -EIO;
+       }
+       spin_unlock_irq(&dev->err_lock);
+       if (retval < 0)
+               goto error;
+
        /* create a urb, and a buffer for it, and copy the data to the urb */
        urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!urb) {
@@ -244,13 +294,14 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
                          usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
                          buf, writesize, skel_write_bulk_callback, dev);
        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+       usb_anchor_urb(urb, &dev->submitted);
 
        /* send the data out the bulk port */
        retval = usb_submit_urb(urb, GFP_KERNEL);
        mutex_unlock(&dev->io_mutex);
        if (retval) {
                err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
-               goto error;
+               goto error_unanchor;
        }
 
        /* release our reference to this urb, the USB core will eventually free it entirely */
@@ -259,6 +310,8 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
 
        return writesize;
 
+error_unanchor:
+       usb_unanchor_urb(urb);
 error:
        if (urb) {
                usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
@@ -276,6 +329,7 @@ static const struct file_operations skel_fops = {
        .write =        skel_write,
        .open =         skel_open,
        .release =      skel_release,
+       .flush =        skel_flush,
 };
 
 /*
@@ -306,6 +360,8 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
        kref_init(&dev->kref);
        sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
        mutex_init(&dev->io_mutex);
+       spin_lock_init(&dev->err_lock);
+       init_usb_anchor(&dev->submitted);
 
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
        dev->interface = interface;
@@ -368,22 +424,18 @@ static void skel_disconnect(struct usb_interface *interface)
        struct usb_skel *dev;
        int minor = interface->minor;
 
-       /* prevent skel_open() from racing skel_disconnect() */
-       mutex_lock(&skel_open_lock);
-
        dev = usb_get_intfdata(interface);
        usb_set_intfdata(interface, NULL);
 
        /* give back our minor */
        usb_deregister_dev(interface, &skel_class);
-       mutex_unlock(&skel_open_lock);
 
        /* prevent more I/O from starting */
        mutex_lock(&dev->io_mutex);
        dev->interface = NULL;
        mutex_unlock(&dev->io_mutex);
 
-
+       usb_kill_anchored_urbs(&dev->submitted);
 
        /* decrement our usage count */
        kref_put(&dev->kref, skel_delete);
@@ -391,10 +443,59 @@ static void skel_disconnect(struct usb_interface *interface)
        info("USB Skeleton #%d now disconnected", minor);
 }
 
+static void skel_draw_down(struct usb_skel *dev)
+{
+       int time;
+
+       time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
+       if (!time)
+               usb_kill_anchored_urbs(&dev->submitted);
+}
+
+static int skel_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct usb_skel *dev = usb_get_intfdata(intf);
+
+       if (!dev)
+               return 0;
+       skel_draw_down(dev);
+       return 0;
+}
+
+static int skel_resume (struct usb_interface *intf)
+{
+       return 0;
+}
+
+static int skel_pre_reset(struct usb_interface *intf)
+{
+       struct usb_skel *dev = usb_get_intfdata(intf);
+
+       mutex_lock(&dev->io_mutex);
+       skel_draw_down(dev);
+
+       return 0;
+}
+
+static int skel_post_reset(struct usb_interface *intf)
+{
+       struct usb_skel *dev = usb_get_intfdata(intf);
+
+       /* we are sure no URBs are active - no locking needed */
+       dev->errors = -EPIPE;
+       mutex_unlock(&dev->io_mutex);
+
+       return 0;
+}
+
 static struct usb_driver skel_driver = {
        .name =         "skeleton",
        .probe =        skel_probe,
        .disconnect =   skel_disconnect,
+       .suspend =      skel_suspend,
+       .resume =       skel_resume,
+       .pre_reset =    skel_pre_reset,
+       .post_reset =   skel_post_reset,
        .id_table =     skel_table,
        .supports_autosuspend = 1,
 };
index 2ce05019301892d9a0420f97ef2b803f8742100a..2349e71b0083f60f87d8dd45b740f81ff1616520 100644 (file)
@@ -2102,7 +2102,9 @@ static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u
 }
 
 
-static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t radeon_show_edid1(struct kobject *kobj,
+                                struct bin_attribute *bin_attr,
+                                char *buf, loff_t off, size_t count)
 {
        struct device *dev = container_of(kobj, struct device, kobj);
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -2113,7 +2115,9 @@ static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, si
 }
 
 
-static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t radeon_show_edid2(struct kobject *kobj,
+                                struct bin_attribute *bin_attr,
+                                char *buf, loff_t off, size_t count)
 {
        struct device *dev = container_of(kobj, struct device, kobj);
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -2126,7 +2130,6 @@ static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, si
 static struct bin_attribute edid1_attr = {
        .attr   = {
                .name   = "edid1",
-               .owner  = THIS_MODULE,
                .mode   = 0444,
        },
        .size   = EDID_LENGTH,
@@ -2136,7 +2139,6 @@ static struct bin_attribute edid1_attr = {
 static struct bin_attribute edid2_attr = {
        .attr   = {
                .name   = "edid2",
-               .owner  = THIS_MODULE,
                .mode   = 0444,
        },
        .size   = EDID_LENGTH,
index c65e81ff3578fedb1ff1e00bde752f252f77a8e0..7e06223bca9494178632f444b989a554f3e5180f 100644 (file)
@@ -172,7 +172,7 @@ static struct class backlight_class = {
 
 #define DECLARE_ATTR(_name,_mode,_show,_store)                 \
 {                                                              \
-       .attr   = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },  \
+       .attr   = { .name = __stringify(_name), .mode = _mode }, \
        .show   = _show,                                        \
        .store  = _store,                                       \
 }
index 6ef8f0a7a137612deb25cbb3377f49e31e8aa93e..648b53c1fdea7f7f2687f8f5d6b60c179f61007a 100644 (file)
@@ -157,7 +157,7 @@ static struct class lcd_class = {
 
 #define DECLARE_ATTR(_name,_mode,_show,_store)                 \
 {                                                              \
-       .attr   = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },  \
+       .attr   = { .name = __stringify(_name), .mode = _mode }, \
        .show   = _show,                                        \
        .store  = _store,                                       \
 }
index 63b85bf81a651d808ab486ebb37b2bc3703c423c..d3b8a6be29163bcfa9523613c8fafb5cc433d7ef 100644 (file)
@@ -6,7 +6,7 @@ menu "Console display driver support"
 
 config VGA_CONSOLE
        bool "VGA text console" if EMBEDDED || !X86
-       depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH
+       depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BFIN
        default y
        help
          Saying Y here will allow you to use Linux in text mode through a
index ab5285a7f1d6b1de4beff23674b8e93981dc28d7..1d3f2080aa6f4ab8ba8eb1fda6bcfc0fae1317f5 100644 (file)
@@ -247,7 +247,6 @@ int SetCoreClockPLL(volatile STG4000REG __iomem *pSTGReg, struct pci_dev *pDev)
        u32 ulCoreClock;
        u32 tmp;
        u32 ulChipSpeed;
-       u8 rev;
 
        STG_WRITE_REG(IntMask, 0xFFFF);
 
@@ -276,9 +275,9 @@ int SetCoreClockPLL(volatile STG4000REG __iomem *pSTGReg, struct pci_dev *pDev)
                      PMX2_SOFTRESET_ROM_RST);
 
        pci_read_config_word(pDev, PCI_CONFIG_SUBSYS_ID, &sub);
-       pci_read_config_byte(pDev, PCI_REVISION_ID, &rev);
 
-       ulChipSpeed = InitSDRAMRegisters(pSTGReg, (u32)sub, (u32)rev);
+       ulChipSpeed = InitSDRAMRegisters(pSTGReg, (u32)sub,
+                                        (u32)pDev->revision);
 
        if (ulChipSpeed == 0)
                return -EINVAL;
index c8559a756b75ff5bbe017c43cea941160d002168..886e475f22f28e395d45066eae6106aa3f4e6c30 100644 (file)
@@ -1994,7 +1994,6 @@ static void matroxfb_unregister_device(struct matrox_fb_info* minfo) {
 
 static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dummy) {
        struct board* b;
-       u_int8_t rev;
        u_int16_t svid;
        u_int16_t sid;
        struct matrox_fb_info* minfo;
@@ -2005,11 +2004,10 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
 #endif
        DBG(__FUNCTION__)
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
        svid = pdev->subsystem_vendor;
        sid = pdev->subsystem_device;
        for (b = dev_list; b->vendor; b++) {
-               if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < rev)) continue;
+               if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < pdev->revision)) continue;
                if (b->svid)
                        if ((b->svid != svid) || (b->sid != sid)) continue;
                break;
index 608e40bb20e9992368a228aae0f5cbf974503745..177177609be77c095fbbd721e5489d53d96e3396 100644 (file)
@@ -2,8 +2,6 @@
 #define __MATROXFB_CRTC2_H__
 
 #include <linux/ioctl.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
 #include "matroxfb_base.h"
 
 struct matroxfb_dh_fb_info {
index a30e1e13d8be87c7c8135ed79c57a54f3e0c691e..93d07ef852762e8d9198adc1d1a3e03a93f8a1ed 100644 (file)
@@ -5789,7 +5789,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        ivideo->warncount = 0;
        ivideo->chip_id = pdev->device;
        ivideo->chip_vendor = pdev->vendor;
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
+       ivideo->revision_id = pdev->revision;
        ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
        pci_read_config_word(pdev, PCI_COMMAND, &reg16);
        ivideo->sisvga_enabled = reg16 & 0x01;
index 62fa5500361d2a1b8a1ce7418c1b81f9d1044d1b..5eff28ce4f4dcfc967583cc2afec2d36ff7eaba6 100644 (file)
@@ -1348,7 +1348,7 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
        f_ddprintk("found device : %s\n", spec->name);
 
        par->dev = pdev;
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &par->revision);
+       par->revision = pdev->revision;
 
        fix->mmio_start = pci_resource_start(pdev,0);
        fix->mmio_len   = 0x400000;
index f0fde6ea7c36e252f5f6dec8d205664d5ce8b023..5c0dab62809972b2b28bc3bd1929e8994e915cae 100644 (file)
@@ -1625,8 +1625,7 @@ tgafb_register(struct device *dev)
        par->tga_regs_base = mem_base + TGA_REGS_OFFSET;
        par->tga_type = tga_type;
        if (tga_bus_pci)
-               pci_read_config_byte(to_pci_dev(dev), PCI_REVISION_ID,
-                                    &par->tga_chip_rev);
+               par->tga_chip_rev = (to_pci_dev(dev))->revision;
        if (tga_bus_tc)
                par->tga_chip_rev = TGA_READ_REG(par, TGA_START_REG) & 0xff;
 
index 8ea17a53eed853223be23df1e78878009ebf5577..cab56005dd49c3d10c90ccaeabe703f877ac8851 100644 (file)
@@ -91,8 +91,9 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
 }
 #endif /* CONFIG_W1_SLAVE_DS2433_CRC */
 
-static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
-                              size_t count)
+static ssize_t w1_f23_read_bin(struct kobject *kobj,
+                              struct bin_attribute *bin_attr,
+                              char *buf, loff_t off, size_t count)
 {
        struct w1_slave *sl = kobj_to_w1_slave(kobj);
 #ifdef CONFIG_W1_SLAVE_DS2433_CRC
@@ -199,8 +200,9 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
        return 0;
 }
 
-static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
-                               size_t count)
+static ssize_t w1_f23_write_bin(struct kobject *kobj,
+                               struct bin_attribute *bin_attr,
+                               char *buf, loff_t off, size_t count)
 {
        struct w1_slave *sl = kobj_to_w1_slave(kobj);
        int addr, len, idx;
@@ -252,7 +254,6 @@ static struct bin_attribute w1_f23_bin_attr = {
        .attr = {
                .name = "eeprom",
                .mode = S_IRUGO | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = W1_EEPROM_SIZE,
        .read = w1_f23_read_bin,
index 1a6937dc190b777369eac30ace6ea0aa665963bc..4318935678c5f68ad1559e4540f233fc30551a35 100644 (file)
@@ -42,13 +42,13 @@ static u8 bad_roms[][9] = {
                                {}
                        };
 
-static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
+static ssize_t w1_therm_read_bin(struct kobject *, struct bin_attribute *,
+                                char *, loff_t, size_t);
 
 static struct bin_attribute w1_therm_bin_attr = {
        .attr = {
                .name = "w1_slave",
                .mode = S_IRUGO,
-               .owner = THIS_MODULE,
        },
        .size = W1_SLAVE_DATA_SIZE,
        .read = w1_therm_read_bin,
@@ -159,7 +159,9 @@ static int w1_therm_check_rom(u8 rom[9])
        return 0;
 }
 
-static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_therm_read_bin(struct kobject *kobj,
+                                struct bin_attribute *bin_attr,
+                                char *buf, loff_t off, size_t count)
 {
        struct w1_slave *sl = kobj_to_w1_slave(kobj);
        struct w1_master *dev = sl->master;
index 7d6876dbcc96a6dcf5cb85f12eb3a10045e52123..f5c5b760ed7b7d9554b7fc3a7f31ee9fc5b27a4c 100644 (file)
@@ -105,7 +105,9 @@ static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *a
        return sprintf(buf, "%s\n", sl->name);
 }
 
-static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_slave_read_id(struct kobject *kobj,
+                               struct bin_attribute *bin_attr,
+                               char *buf, loff_t off, size_t count)
 {
        struct w1_slave *sl = kobj_to_w1_slave(kobj);
 
@@ -128,7 +130,6 @@ static struct bin_attribute w1_slave_attr_bin_id = {
       .attr = {
               .name = "id",
               .mode = S_IRUGO,
-              .owner = THIS_MODULE,
       },
       .size = 8,
       .read = w1_slave_read_id,
@@ -136,7 +137,9 @@ static struct bin_attribute w1_slave_attr_bin_id = {
 
 /* Default family */
 
-static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_default_write(struct kobject *kobj,
+                               struct bin_attribute *bin_attr,
+                               char *buf, loff_t off, size_t count)
 {
        struct w1_slave *sl = kobj_to_w1_slave(kobj);
 
@@ -153,7 +156,9 @@ out_up:
        return count;
 }
 
-static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_default_read(struct kobject *kobj,
+                              struct bin_attribute *bin_attr,
+                              char *buf, loff_t off, size_t count)
 {
        struct w1_slave *sl = kobj_to_w1_slave(kobj);
 
@@ -167,7 +172,6 @@ static struct bin_attribute w1_default_attr = {
       .attr = {
               .name = "rw",
               .mode = S_IRUGO | S_IWUSR,
-              .owner = THIS_MODULE,
       },
       .size = PAGE_SIZE,
       .read = w1_default_read,
index c3ba0ec334c45a419513343d7abd505633364482..9130f1c12c265887d02633ef932fe31fadc5526f 100644 (file)
@@ -49,8 +49,9 @@ static ssize_t zorro_show_resource(struct device *dev, struct device_attribute *
 
 static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL);
 
-static ssize_t zorro_read_config(struct kobject *kobj, char *buf, loff_t off,
-                                size_t count)
+static ssize_t zorro_read_config(struct kobject *kobj,
+                                struct bin_attribute *bin_attr,
+                                char *buf, loff_t off, size_t count)
 {
        struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device,
                                           kobj));
@@ -78,7 +79,6 @@ static struct bin_attribute zorro_config_attr = {
        .attr = {
                .name = "config",
                .mode = S_IRUGO | S_IWUSR,
-               .owner = THIS_MODULE
        },
        .size = sizeof(struct ConfigDev),
        .read = zorro_read_config,
index ec8896b264de53759f119769cf158daacb1d068c..1d533a2ec3a6df41433ba9662c4d3867097902f5 100644 (file)
@@ -368,6 +368,69 @@ void debugfs_remove(struct dentry *dentry)
 }
 EXPORT_SYMBOL_GPL(debugfs_remove);
 
+/**
+ * debugfs_rename - rename a file/directory in the debugfs filesystem
+ * @old_dir: a pointer to the parent dentry for the renamed object. This
+ *          should be a directory dentry.
+ * @old_dentry: dentry of an object to be renamed.
+ * @new_dir: a pointer to the parent dentry where the object should be
+ *          moved. This should be a directory dentry.
+ * @new_name: a pointer to a string containing the target name.
+ *
+ * This function renames a file/directory in debugfs.  The target must not
+ * exist for rename to succeed.
+ *
+ * This function will return a pointer to old_dentry (which is updated to
+ * reflect renaming) if it succeeds. If an error occurs, %NULL will be
+ * returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
+               struct dentry *new_dir, const char *new_name)
+{
+       int error;
+       struct dentry *dentry = NULL, *trap;
+       const char *old_name;
+
+       trap = lock_rename(new_dir, old_dir);
+       /* Source or destination directories don't exist? */
+       if (!old_dir->d_inode || !new_dir->d_inode)
+               goto exit;
+       /* Source does not exist, cyclic rename, or mountpoint? */
+       if (!old_dentry->d_inode || old_dentry == trap ||
+           d_mountpoint(old_dentry))
+               goto exit;
+       dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
+       /* Lookup failed, cyclic rename or target exists? */
+       if (IS_ERR(dentry) || dentry == trap || dentry->d_inode)
+               goto exit;
+
+       old_name = fsnotify_oldname_init(old_dentry->d_name.name);
+
+       error = simple_rename(old_dir->d_inode, old_dentry, new_dir->d_inode,
+               dentry);
+       if (error) {
+               fsnotify_oldname_free(old_name);
+               goto exit;
+       }
+       d_move(old_dentry, dentry);
+       fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
+               old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode),
+               NULL, old_dentry->d_inode);
+       fsnotify_oldname_free(old_name);
+       unlock_rename(new_dir, old_dir);
+       dput(dentry);
+       return old_dentry;
+exit:
+       if (dentry && !IS_ERR(dentry))
+               dput(dentry);
+       unlock_rename(new_dir, old_dir);
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(debugfs_rename);
+
 static decl_subsys(debug, NULL, NULL);
 
 static int __init debugfs_init(void)
index 606128f5c927d3697c04f4f84ee64718e9cfd71b..02ca6f1e55d77d09ddd4d057c9e02bdc8c33ef5a 100644 (file)
@@ -840,8 +840,6 @@ static int __init ecryptfs_init(void)
                goto out;
        }
        kobj_set_kset_s(&ecryptfs_subsys, fs_subsys);
-       sysfs_attr_version.attr.owner = THIS_MODULE;
-       sysfs_attr_version_str.attr.owner = THIS_MODULE;
        rc = do_sysfs_registration();
        if (rc) {
                printk(KERN_ERR "sysfs registration failed\n");
index 96070bff93fc5c9f0ec91cef0c6abadfbf26e1e5..572601e98dcdec6d6d88da33ec0b757bd8b7d3f4 100644 (file)
@@ -44,9 +44,8 @@ static struct nsm_handle *    nsm_find(const struct sockaddr_in *sin,
  */
 static struct nlm_host *
 nlm_lookup_host(int server, const struct sockaddr_in *sin,
-                                       int proto, int version,
-                                       const char *hostname,
-                                       int hostname_len)
+               int proto, int version, const char *hostname,
+               int hostname_len, const struct sockaddr_in *ssin)
 {
        struct hlist_head *chain;
        struct hlist_node *pos;
@@ -54,7 +53,9 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
        struct nsm_handle *nsm = NULL;
        int             hash;
 
-       dprintk("lockd: nlm_lookup_host(%u.%u.%u.%u, p=%d, v=%d, my role=%s, name=%.*s)\n",
+       dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT
+                       ", p=%d, v=%d, my role=%s, name=%.*s)\n",
+                       NIPQUAD(ssin->sin_addr.s_addr),
                        NIPQUAD(sin->sin_addr.s_addr), proto, version,
                        server? "server" : "client",
                        hostname_len,
@@ -91,6 +92,8 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
                        continue;
                if (host->h_server != server)
                        continue;
+               if (!nlm_cmp_addr(&host->h_saddr, ssin))
+                       continue;
 
                /* Move to head of hash chain. */
                hlist_del(&host->h_hash);
@@ -118,6 +121,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
        host->h_name       = nsm->sm_name;
        host->h_addr       = *sin;
        host->h_addr.sin_port = 0;      /* ouch! */
+       host->h_saddr      = *ssin;
        host->h_version    = version;
        host->h_proto      = proto;
        host->h_rpcclnt    = NULL;
@@ -161,15 +165,9 @@ nlm_destroy_host(struct nlm_host *host)
         */
        nsm_unmonitor(host);
 
-       if ((clnt = host->h_rpcclnt) != NULL) {
-               if (atomic_read(&clnt->cl_users)) {
-                       printk(KERN_WARNING
-                               "lockd: active RPC handle\n");
-                       clnt->cl_dead = 1;
-               } else {
-                       rpc_destroy_client(host->h_rpcclnt);
-               }
-       }
+       clnt = host->h_rpcclnt;
+       if (clnt != NULL)
+               rpc_shutdown_client(clnt);
        kfree(host);
 }
 
@@ -180,8 +178,10 @@ struct nlm_host *
 nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
                        const char *hostname, int hostname_len)
 {
+       struct sockaddr_in ssin = {0};
+
        return nlm_lookup_host(0, sin, proto, version,
-                              hostname, hostname_len);
+                              hostname, hostname_len, &ssin);
 }
 
 /*
@@ -191,9 +191,12 @@ struct nlm_host *
 nlmsvc_lookup_host(struct svc_rqst *rqstp,
                        const char *hostname, int hostname_len)
 {
+       struct sockaddr_in ssin = {0};
+
+       ssin.sin_addr = rqstp->rq_daddr.addr;
        return nlm_lookup_host(1, svc_addr_in(rqstp),
                               rqstp->rq_prot, rqstp->rq_vers,
-                              hostname, hostname_len);
+                              hostname, hostname_len, &ssin);
 }
 
 /*
@@ -204,8 +207,9 @@ nlm_bind_host(struct nlm_host *host)
 {
        struct rpc_clnt *clnt;
 
-       dprintk("lockd: nlm_bind_host(%08x)\n",
-                       (unsigned)ntohl(host->h_addr.sin_addr.s_addr));
+       dprintk("lockd: nlm_bind_host("NIPQUAD_FMT"->"NIPQUAD_FMT")\n",
+                       NIPQUAD(host->h_saddr.sin_addr),
+                       NIPQUAD(host->h_addr.sin_addr));
 
        /* Lock host handle */
        mutex_lock(&host->h_mutex);
@@ -232,6 +236,7 @@ nlm_bind_host(struct nlm_host *host)
                        .protocol       = host->h_proto,
                        .address        = (struct sockaddr *)&host->h_addr,
                        .addrsize       = sizeof(host->h_addr),
+                       .saddress       = (struct sockaddr *)&host->h_saddr,
                        .timeout        = &timeparms,
                        .servername     = host->h_name,
                        .program        = &nlm_program,
index 2102e2d0134dc2db7c9a50da58a29f35aea34711..3353ed8421a7af49e69e98758860d7d7754f7185 100644 (file)
@@ -61,6 +61,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
                        status);
        else
                status = 0;
+       rpc_shutdown_client(clnt);
  out:
        return status;
 }
@@ -138,7 +139,6 @@ nsm_create(void)
                .program        = &nsm_program,
                .version        = SM_VERSION,
                .authflavor     = RPC_AUTH_NULL,
-               .flags          = (RPC_CLNT_CREATE_ONESHOT),
        };
 
        return rpc_create(&args);
index 126b1bf02c0ec2d8b5c051eb1e29acf27d6a32b3..26809325469cdc73bafa76dec33e52cfa046f548 100644 (file)
@@ -123,9 +123,6 @@ lockd(struct svc_rqst *rqstp)
        /* Process request with signals blocked, but allow SIGKILL.  */
        allow_signal(SIGKILL);
 
-       /* kick rpciod */
-       rpciod_up();
-
        dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
 
        if (!nlm_timeout)
@@ -202,9 +199,6 @@ lockd(struct svc_rqst *rqstp)
        /* Exit the RPC thread */
        svc_exit_thread(rqstp);
 
-       /* release rpciod */
-       rpciod_down();
-
        /* Release module */
        unlock_kernel();
        module_put_and_exit(0);
index f4580b44eef4b02ee0045c5732cf29d0d6efa347..b55cb236cf74c0be1adf41d43e21e71d298fa1b5 100644 (file)
@@ -6,8 +6,8 @@ obj-$(CONFIG_NFS_FS) += nfs.o
 
 nfs-y                  := client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \
                           pagelist.o proc.o read.o symlink.o unlink.o \
-                          write.o namespace.o
-nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o      
+                          write.o namespace.o mount_clnt.o
+nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
 nfs-$(CONFIG_NFS_V3)   += nfs3proc.o nfs3xdr.o
 nfs-$(CONFIG_NFS_V3_ACL)       += nfs3acl.o
 nfs-$(CONFIG_NFS_V4)   += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
index 881fa490092393c97ee5c69dd2cfe33e6bd9c3c0..ccb455053ee48090ab21b4bdd55294d3f4694010 100644 (file)
@@ -102,19 +102,10 @@ static struct nfs_client *nfs_alloc_client(const char *hostname,
                                           int nfsversion)
 {
        struct nfs_client *clp;
-       int error;
 
        if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
                goto error_0;
 
-       error = rpciod_up();
-       if (error < 0) {
-               dprintk("%s: couldn't start rpciod! Error = %d\n",
-                               __FUNCTION__, error);
-               goto error_1;
-       }
-       __set_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
-
        if (nfsversion == 4) {
                if (nfs_callback_up() < 0)
                        goto error_2;
@@ -139,8 +130,6 @@ static struct nfs_client *nfs_alloc_client(const char *hostname,
 #ifdef CONFIG_NFS_V4
        init_rwsem(&clp->cl_sem);
        INIT_LIST_HEAD(&clp->cl_delegations);
-       INIT_LIST_HEAD(&clp->cl_state_owners);
-       INIT_LIST_HEAD(&clp->cl_unused);
        spin_lock_init(&clp->cl_lock);
        INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
        rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
@@ -154,9 +143,6 @@ error_3:
        if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
                nfs_callback_down();
 error_2:
-       rpciod_down();
-       __clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
-error_1:
        kfree(clp);
 error_0:
        return NULL;
@@ -167,16 +153,7 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
 #ifdef CONFIG_NFS_V4
        if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
                nfs4_kill_renewd(clp);
-       while (!list_empty(&clp->cl_unused)) {
-               struct nfs4_state_owner *sp;
-
-               sp = list_entry(clp->cl_unused.next,
-                               struct nfs4_state_owner,
-                               so_list);
-               list_del(&sp->so_list);
-               kfree(sp);
-       }
-       BUG_ON(!list_empty(&clp->cl_state_owners));
+       BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
        if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
                nfs_idmap_delete(clp);
 #endif
@@ -198,9 +175,6 @@ static void nfs_free_client(struct nfs_client *clp)
        if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
                nfs_callback_down();
 
-       if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state))
-               rpciod_down();
-
        kfree(clp->cl_hostname);
        kfree(clp);
 
index 7f37d1bea83fc3f8c4bdadb968c4f295e1b32cd7..20ac403469a02b11998d553a6e54af63c92f20c2 100644 (file)
@@ -27,6 +27,13 @@ static void nfs_free_delegation(struct nfs_delegation *delegation)
        kfree(delegation);
 }
 
+static void nfs_free_delegation_callback(struct rcu_head *head)
+{
+       struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu);
+
+       nfs_free_delegation(delegation);
+}
+
 static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
 {
        struct inode *inode = state->inode;
@@ -57,7 +64,7 @@ out_err:
        return status;
 }
 
-static void nfs_delegation_claim_opens(struct inode *inode)
+static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_open_context *ctx;
@@ -72,9 +79,11 @@ again:
                        continue;
                if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
                        continue;
+               if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
+                       continue;
                get_nfs_open_context(ctx);
                spin_unlock(&inode->i_lock);
-               err = nfs4_open_delegation_recall(ctx->dentry, state);
+               err = nfs4_open_delegation_recall(ctx, state, stateid);
                if (err >= 0)
                        err = nfs_delegation_claim_locks(ctx, state);
                put_nfs_open_context(ctx);
@@ -115,10 +124,6 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
        struct nfs_delegation *delegation;
        int status = 0;
 
-       /* Ensure we first revalidate the attributes and page cache! */
-       if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR)))
-               __nfs_revalidate_inode(NFS_SERVER(inode), inode);
-
        delegation = kmalloc(sizeof(*delegation), GFP_KERNEL);
        if (delegation == NULL)
                return -ENOMEM;
@@ -131,10 +136,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
        delegation->inode = inode;
 
        spin_lock(&clp->cl_lock);
-       if (nfsi->delegation == NULL) {
-               list_add(&delegation->super_list, &clp->cl_delegations);
-               nfsi->delegation = delegation;
+       if (rcu_dereference(nfsi->delegation) == NULL) {
+               list_add_rcu(&delegation->super_list, &clp->cl_delegations);
                nfsi->delegation_state = delegation->type;
+               rcu_assign_pointer(nfsi->delegation, delegation);
                delegation = NULL;
        } else {
                if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
@@ -145,6 +150,12 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
                        status = -EIO;
                }
        }
+
+       /* Ensure we revalidate the attributes and page cache! */
+       spin_lock(&inode->i_lock);
+       nfsi->cache_validity |= NFS_INO_REVAL_FORCED;
+       spin_unlock(&inode->i_lock);
+
        spin_unlock(&clp->cl_lock);
        kfree(delegation);
        return status;
@@ -155,7 +166,7 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
        int res = 0;
 
        res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid);
-       nfs_free_delegation(delegation);
+       call_rcu(&delegation->rcu, nfs_free_delegation_callback);
        return res;
 }
 
@@ -170,33 +181,55 @@ static void nfs_msync_inode(struct inode *inode)
 /*
  * Basic procedure for returning a delegation to the server
  */
-int __nfs_inode_return_delegation(struct inode *inode)
+static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
 {
        struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
        struct nfs_inode *nfsi = NFS_I(inode);
-       struct nfs_delegation *delegation;
-       int res = 0;
 
        nfs_msync_inode(inode);
        down_read(&clp->cl_sem);
        /* Guard against new delegated open calls */
        down_write(&nfsi->rwsem);
-       spin_lock(&clp->cl_lock);
-       delegation = nfsi->delegation;
-       if (delegation != NULL) {
-               list_del_init(&delegation->super_list);
-               nfsi->delegation = NULL;
-               nfsi->delegation_state = 0;
-       }
-       spin_unlock(&clp->cl_lock);
-       nfs_delegation_claim_opens(inode);
+       nfs_delegation_claim_opens(inode, &delegation->stateid);
        up_write(&nfsi->rwsem);
        up_read(&clp->cl_sem);
        nfs_msync_inode(inode);
 
-       if (delegation != NULL)
-               res = nfs_do_return_delegation(inode, delegation);
-       return res;
+       return nfs_do_return_delegation(inode, delegation);
+}
+
+static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid)
+{
+       struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation);
+
+       if (delegation == NULL)
+               goto nomatch;
+       if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data,
+                               sizeof(delegation->stateid.data)) != 0)
+               goto nomatch;
+       list_del_rcu(&delegation->super_list);
+       nfsi->delegation_state = 0;
+       rcu_assign_pointer(nfsi->delegation, NULL);
+       return delegation;
+nomatch:
+       return NULL;
+}
+
+int nfs_inode_return_delegation(struct inode *inode)
+{
+       struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
+       struct nfs_inode *nfsi = NFS_I(inode);
+       struct nfs_delegation *delegation;
+       int err = 0;
+
+       if (rcu_dereference(nfsi->delegation) != NULL) {
+               spin_lock(&clp->cl_lock);
+               delegation = nfs_detach_delegation_locked(nfsi, NULL);
+               spin_unlock(&clp->cl_lock);
+               if (delegation != NULL)
+                       err = __nfs_inode_return_delegation(inode, delegation);
+       }
+       return err;
 }
 
 /*
@@ -211,19 +244,23 @@ void nfs_return_all_delegations(struct super_block *sb)
        if (clp == NULL)
                return;
 restart:
-       spin_lock(&clp->cl_lock);
-       list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
                if (delegation->inode->i_sb != sb)
                        continue;
                inode = igrab(delegation->inode);
                if (inode == NULL)
                        continue;
+               spin_lock(&clp->cl_lock);
+               delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
                spin_unlock(&clp->cl_lock);
-               nfs_inode_return_delegation(inode);
+               rcu_read_unlock();
+               if (delegation != NULL)
+                       __nfs_inode_return_delegation(inode, delegation);
                iput(inode);
                goto restart;
        }
-       spin_unlock(&clp->cl_lock);
+       rcu_read_unlock();
 }
 
 static int nfs_do_expire_all_delegations(void *ptr)
@@ -234,22 +271,26 @@ static int nfs_do_expire_all_delegations(void *ptr)
 
        allow_signal(SIGKILL);
 restart:
-       spin_lock(&clp->cl_lock);
        if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0)
                goto out;
        if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0)
                goto out;
-       list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
                inode = igrab(delegation->inode);
                if (inode == NULL)
                        continue;
+               spin_lock(&clp->cl_lock);
+               delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
                spin_unlock(&clp->cl_lock);
-               nfs_inode_return_delegation(inode);
+               rcu_read_unlock();
+               if (delegation)
+                       __nfs_inode_return_delegation(inode, delegation);
                iput(inode);
                goto restart;
        }
+       rcu_read_unlock();
 out:
-       spin_unlock(&clp->cl_lock);
        nfs_put_client(clp);
        module_put_and_exit(0);
 }
@@ -280,17 +321,21 @@ void nfs_handle_cb_pathdown(struct nfs_client *clp)
        if (clp == NULL)
                return;
 restart:
-       spin_lock(&clp->cl_lock);
-       list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
                inode = igrab(delegation->inode);
                if (inode == NULL)
                        continue;
+               spin_lock(&clp->cl_lock);
+               delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
                spin_unlock(&clp->cl_lock);
-               nfs_inode_return_delegation(inode);
+               rcu_read_unlock();
+               if (delegation != NULL)
+                       __nfs_inode_return_delegation(inode, delegation);
                iput(inode);
                goto restart;
        }
-       spin_unlock(&clp->cl_lock);
+       rcu_read_unlock();
 }
 
 struct recall_threadargs {
@@ -316,21 +361,14 @@ static int recall_thread(void *data)
        down_read(&clp->cl_sem);
        down_write(&nfsi->rwsem);
        spin_lock(&clp->cl_lock);
-       delegation = nfsi->delegation;
-       if (delegation != NULL && memcmp(delegation->stateid.data,
-                               args->stateid->data,
-                               sizeof(delegation->stateid.data)) == 0) {
-               list_del_init(&delegation->super_list);
-               nfsi->delegation = NULL;
-               nfsi->delegation_state = 0;
+       delegation = nfs_detach_delegation_locked(nfsi, args->stateid);
+       if (delegation != NULL)
                args->result = 0;
-       } else {
-               delegation = NULL;
+       else
                args->result = -ENOENT;
-       }
        spin_unlock(&clp->cl_lock);
        complete(&args->started);
-       nfs_delegation_claim_opens(inode);
+       nfs_delegation_claim_opens(inode, args->stateid);
        up_write(&nfsi->rwsem);
        up_read(&clp->cl_sem);
        nfs_msync_inode(inode);
@@ -371,14 +409,14 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs
 {
        struct nfs_delegation *delegation;
        struct inode *res = NULL;
-       spin_lock(&clp->cl_lock);
-       list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
                if (nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
                        res = igrab(delegation->inode);
                        break;
                }
        }
-       spin_unlock(&clp->cl_lock);
+       rcu_read_unlock();
        return res;
 }
 
@@ -388,10 +426,10 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs
 void nfs_delegation_mark_reclaim(struct nfs_client *clp)
 {
        struct nfs_delegation *delegation;
-       spin_lock(&clp->cl_lock);
-       list_for_each_entry(delegation, &clp->cl_delegations, super_list)
+       rcu_read_lock();
+       list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list)
                delegation->flags |= NFS_DELEGATION_NEED_RECLAIM;
-       spin_unlock(&clp->cl_lock);
+       rcu_read_unlock();
 }
 
 /*
@@ -399,39 +437,35 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp)
  */
 void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
 {
-       struct nfs_delegation *delegation, *n;
-       LIST_HEAD(head);
-       spin_lock(&clp->cl_lock);
-       list_for_each_entry_safe(delegation, n, &clp->cl_delegations, super_list) {
+       struct nfs_delegation *delegation;
+restart:
+       rcu_read_lock();
+       list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
                if ((delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0)
                        continue;
-               list_move(&delegation->super_list, &head);
-               NFS_I(delegation->inode)->delegation = NULL;
-               NFS_I(delegation->inode)->delegation_state = 0;
-       }
-       spin_unlock(&clp->cl_lock);
-       while(!list_empty(&head)) {
-               delegation = list_entry(head.next, struct nfs_delegation, super_list);
-               list_del(&delegation->super_list);
-               nfs_free_delegation(delegation);
+               spin_lock(&clp->cl_lock);
+               delegation = nfs_detach_delegation_locked(NFS_I(delegation->inode), NULL);
+               spin_unlock(&clp->cl_lock);
+               rcu_read_unlock();
+               if (delegation != NULL)
+                       call_rcu(&delegation->rcu, nfs_free_delegation_callback);
+               goto restart;
        }
+       rcu_read_unlock();
 }
 
 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
 {
-       struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_delegation *delegation;
-       int res = 0;
+       int ret = 0;
 
-       if (nfsi->delegation_state == 0)
-               return 0;
-       spin_lock(&clp->cl_lock);
-       delegation = nfsi->delegation;
+       rcu_read_lock();
+       delegation = rcu_dereference(nfsi->delegation);
        if (delegation != NULL) {
                memcpy(dst->data, delegation->stateid.data, sizeof(dst->data));
-               res = 1;
+               ret = 1;
        }
-       spin_unlock(&clp->cl_lock);
-       return res;
+       rcu_read_unlock();
+       return ret;
 }
index 2cfd4b24c7feb0d8c4e8c3ec4f5ef8964feef765..5874ce7fdbaee12339a0d6910af6fcdc6f578848 100644 (file)
@@ -22,11 +22,12 @@ struct nfs_delegation {
        long flags;
        loff_t maxsize;
        __u64 change_attr;
+       struct rcu_head rcu;
 };
 
 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
 void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
-int __nfs_inode_return_delegation(struct inode *inode);
+int nfs_inode_return_delegation(struct inode *inode);
 int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
 
 struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle);
@@ -39,27 +40,24 @@ void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
 
 /* NFSv4 delegation-related procedures */
 int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
-int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
 int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
 
 static inline int nfs_have_delegation(struct inode *inode, int flags)
 {
+       struct nfs_delegation *delegation;
+       int ret = 0;
+
        flags &= FMODE_READ|FMODE_WRITE;
-       smp_rmb();
-       if ((NFS_I(inode)->delegation_state & flags) == flags)
-               return 1;
-       return 0;
+       rcu_read_lock();
+       delegation = rcu_dereference(NFS_I(inode)->delegation);
+       if (delegation != NULL && (delegation->type & flags) == flags)
+               ret = 1;
+       rcu_read_unlock();
+       return ret;
 }
 
-static inline int nfs_inode_return_delegation(struct inode *inode)
-{
-       int err = 0;
-
-       if (NFS_I(inode)->delegation != NULL)
-               err = __nfs_inode_return_delegation(inode);
-       return err;
-}
 #else
 static inline int nfs_have_delegation(struct inode *inode, int flags)
 {
index c27258b5d3e16a55f16f85981e92a22854de3583..322141f4ab4810f5230898c2f1773e5290476242 100644 (file)
@@ -897,14 +897,13 @@ int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
        return (nd->intent.open.flags & O_EXCL) != 0;
 }
 
-static inline int nfs_reval_fsid(struct vfsmount *mnt, struct inode *dir,
-                                struct nfs_fh *fh, struct nfs_fattr *fattr)
+static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr)
 {
        struct nfs_server *server = NFS_SERVER(dir);
 
        if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
-               /* Revalidate fsid on root dir */
-               return __nfs_revalidate_inode(server, mnt->mnt_root->d_inode);
+               /* Revalidate fsid using the parent directory */
+               return __nfs_revalidate_inode(server, dir);
        return 0;
 }
 
@@ -946,7 +945,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
                res = ERR_PTR(error);
                goto out_unlock;
        }
-       error = nfs_reval_fsid(nd->mnt, dir, &fhandle, &fattr);
+       error = nfs_reval_fsid(dir, &fattr);
        if (error < 0) {
                res = ERR_PTR(error);
                goto out_unlock;
@@ -1244,7 +1243,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
        attr.ia_mode = mode;
        attr.ia_valid = ATTR_MODE;
 
-       if (nd && (nd->flags & LOOKUP_CREATE))
+       if ((nd->flags & LOOKUP_CREATE) != 0)
                open_flags = nd->intent.open.flags;
 
        lock_kernel();
@@ -1535,7 +1534,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
 
        lock_kernel();
 
-       page = alloc_page(GFP_KERNEL);
+       page = alloc_page(GFP_HIGHUSER);
        if (!page) {
                unlock_kernel();
                return -ENOMEM;
@@ -1744,8 +1743,8 @@ int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
        struct nfs_inode *nfsi;
        struct nfs_access_entry *cache;
 
-       spin_lock(&nfs_access_lru_lock);
 restart:
+       spin_lock(&nfs_access_lru_lock);
        list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) {
                struct inode *inode;
 
@@ -1770,6 +1769,7 @@ remove_lru_entry:
                        clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags);
                }
                spin_unlock(&inode->i_lock);
+               spin_unlock(&nfs_access_lru_lock);
                iput(inode);
                goto restart;
        }
index 00eee87510fe5b5438aa21556298cdebfc294804..a5c82b6f3b4556918aa169da26ce43c45c4a6f00 100644 (file)
@@ -266,7 +266,7 @@ static const struct rpc_call_ops nfs_read_direct_ops = {
 static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos)
 {
        struct nfs_open_context *ctx = dreq->ctx;
-       struct inode *inode = ctx->dentry->d_inode;
+       struct inode *inode = ctx->path.dentry->d_inode;
        size_t rsize = NFS_SERVER(inode)->rsize;
        unsigned int pgbase;
        int result;
@@ -295,9 +295,14 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo
                        break;
                }
                if ((unsigned)result < data->npages) {
-                       nfs_direct_release_pages(data->pagevec, result);
-                       nfs_readdata_release(data);
-                       break;
+                       bytes = result * PAGE_SIZE;
+                       if (bytes <= pgbase) {
+                               nfs_direct_release_pages(data->pagevec, result);
+                               nfs_readdata_release(data);
+                               break;
+                       }
+                       bytes -= pgbase;
+                       data->npages = result;
                }
 
                get_dreq(dreq);
@@ -601,7 +606,7 @@ static const struct rpc_call_ops nfs_write_direct_ops = {
 static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync)
 {
        struct nfs_open_context *ctx = dreq->ctx;
-       struct inode *inode = ctx->dentry->d_inode;
+       struct inode *inode = ctx->path.dentry->d_inode;
        size_t wsize = NFS_SERVER(inode)->wsize;
        unsigned int pgbase;
        int result;
@@ -630,9 +635,14 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l
                        break;
                }
                if ((unsigned)result < data->npages) {
-                       nfs_direct_release_pages(data->pagevec, result);
-                       nfs_writedata_release(data);
-                       break;
+                       bytes = result * PAGE_SIZE;
+                       if (bytes <= pgbase) {
+                               nfs_direct_release_pages(data->pagevec, result);
+                               nfs_writedata_release(data);
+                               break;
+                       }
+                       bytes -= pgbase;
+                       data->npages = result;
                }
 
                get_dreq(dreq);
@@ -763,10 +773,8 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
                (unsigned long) count, (long long) pos);
 
        if (nr_segs != 1)
-               return -EINVAL;
-
-       if (count < 0)
                goto out;
+
        retval = -EFAULT;
        if (!access_ok(VERIFY_WRITE, buf, count))
                goto out;
@@ -814,7 +822,7 @@ out:
 ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos)
 {
-       ssize_t retval;
+       ssize_t retval = -EINVAL;
        struct file *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
        /* XXX: temporary */
@@ -827,7 +835,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
                (unsigned long) count, (long long) pos);
 
        if (nr_segs != 1)
-               return -EINVAL;
+               goto out;
 
        retval = generic_write_checks(file, &pos, &count, 0);
        if (retval)
index bd9f5a8365923ca12566af9ffa12848892987efa..3d9fccf4ef93eb9f51c01f2fa7d3e435ca881216 100644 (file)
@@ -461,14 +461,14 @@ static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, str
 
        ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
        if (ctx != NULL) {
-               atomic_set(&ctx->count, 1);
-               ctx->dentry = dget(dentry);
-               ctx->vfsmnt = mntget(mnt);
+               ctx->path.dentry = dget(dentry);
+               ctx->path.mnt = mntget(mnt);
                ctx->cred = get_rpccred(cred);
                ctx->state = NULL;
                ctx->lockowner = current->files;
                ctx->error = 0;
                ctx->dir_cookie = 0;
+               kref_init(&ctx->kref);
        }
        return ctx;
 }
@@ -476,27 +476,33 @@ static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, str
 struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
 {
        if (ctx != NULL)
-               atomic_inc(&ctx->count);
+               kref_get(&ctx->kref);
        return ctx;
 }
 
-void put_nfs_open_context(struct nfs_open_context *ctx)
+static void nfs_free_open_context(struct kref *kref)
 {
-       if (atomic_dec_and_test(&ctx->count)) {
-               if (!list_empty(&ctx->list)) {
-                       struct inode *inode = ctx->dentry->d_inode;
-                       spin_lock(&inode->i_lock);
-                       list_del(&ctx->list);
-                       spin_unlock(&inode->i_lock);
-               }
-               if (ctx->state != NULL)
-                       nfs4_close_state(ctx->state, ctx->mode);
-               if (ctx->cred != NULL)
-                       put_rpccred(ctx->cred);
-               dput(ctx->dentry);
-               mntput(ctx->vfsmnt);
-               kfree(ctx);
+       struct nfs_open_context *ctx = container_of(kref,
+                       struct nfs_open_context, kref);
+
+       if (!list_empty(&ctx->list)) {
+               struct inode *inode = ctx->path.dentry->d_inode;
+               spin_lock(&inode->i_lock);
+               list_del(&ctx->list);
+               spin_unlock(&inode->i_lock);
        }
+       if (ctx->state != NULL)
+               nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
+       if (ctx->cred != NULL)
+               put_rpccred(ctx->cred);
+       dput(ctx->path.dentry);
+       mntput(ctx->path.mnt);
+       kfree(ctx);
+}
+
+void put_nfs_open_context(struct nfs_open_context *ctx)
+{
+       kref_put(&ctx->kref, nfs_free_open_context);
 }
 
 /*
@@ -961,8 +967,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                goto out_changed;
 
        server = NFS_SERVER(inode);
-       /* Update the fsid if and only if this is the root directory */
-       if (inode == inode->i_sb->s_root->d_inode
+       /* Update the fsid? */
+       if (S_ISDIR(inode->i_mode)
                        && !nfs_fsid_equal(&server->fsid, &fattr->fsid))
                server->fsid = fattr->fsid;
 
@@ -1066,8 +1072,10 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                invalid &= ~NFS_INO_INVALID_DATA;
        if (data_stable)
                invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE);
-       if (!nfs_have_delegation(inode, FMODE_READ))
+       if (!nfs_have_delegation(inode, FMODE_READ) ||
+                       (nfsi->cache_validity & NFS_INO_REVAL_FORCED))
                nfsi->cache_validity |= invalid;
+       nfsi->cache_validity &= ~NFS_INO_REVAL_FORCED;
 
        return 0;
  out_changed:
@@ -1103,27 +1111,10 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
  */
 void nfs4_clear_inode(struct inode *inode)
 {
-       struct nfs_inode *nfsi = NFS_I(inode);
-
        /* If we are holding a delegation, return it! */
        nfs_inode_return_delegation(inode);
        /* First call standard NFS clear_inode() code */
        nfs_clear_inode(inode);
-       /* Now clear out any remaining state */
-       while (!list_empty(&nfsi->open_states)) {
-               struct nfs4_state *state;
-               
-               state = list_entry(nfsi->open_states.next,
-                               struct nfs4_state,
-                               inode_states);
-               dprintk("%s(%s/%Ld): found unclaimed NFSv4 state %p\n",
-                               __FUNCTION__,
-                               inode->i_sb->s_id,
-                               (long long)NFS_FILEID(inode),
-                               state);
-               BUG_ON(atomic_read(&state->count) != 1);
-               nfs4_close_state(state, state->state);
-       }
 }
 #endif
 
@@ -1165,15 +1156,11 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
        struct nfs_inode *nfsi = (struct nfs_inode *) foo;
 
        inode_init_once(&nfsi->vfs_inode);
-       spin_lock_init(&nfsi->req_lock);
-       INIT_LIST_HEAD(&nfsi->dirty);
-       INIT_LIST_HEAD(&nfsi->commit);
        INIT_LIST_HEAD(&nfsi->open_files);
        INIT_LIST_HEAD(&nfsi->access_cache_entry_lru);
        INIT_LIST_HEAD(&nfsi->access_cache_inode_lru);
        INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
        atomic_set(&nfsi->data_updates, 0);
-       nfsi->ndirty = 0;
        nfsi->ncommit = 0;
        nfsi->npages = 0;
        nfs4_init_once(nfsi);
index ad2b40db1e65f901d7081c27ed0b9650816a8f6d..76cf55d57101ab5b2cf3acfac638684e27bb6543 100644 (file)
@@ -183,9 +183,9 @@ unsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp)
 /*
  * Calculate the number of 512byte blocks used.
  */
-static inline unsigned long nfs_calc_block_size(u64 tsize)
+static inline blkcnt_t nfs_calc_block_size(u64 tsize)
 {
-       loff_t used = (tsize + 511) >> 9;
+       blkcnt_t used = (tsize + 511) >> 9;
        return (used > ULONG_MAX) ? ULONG_MAX : used;
 }
 
index ca5a266a3140430266e7c57a2292134218cad6c1..8afd9f7e7a97c075faad46eace3c3e111abb8053 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * linux/fs/nfs/mount_clnt.c
- *
- * MOUNT client to support NFSroot.
+ * In-kernel MOUNT protocol client
  *
  * Copyright (C) 1997, Olaf Kirch <okir@monad.swb.de>
  */
 #include <linux/nfs_fs.h>
 
 #ifdef RPC_DEBUG
-# define NFSDBG_FACILITY       NFSDBG_ROOT
+# define NFSDBG_FACILITY       NFSDBG_MOUNT
 #endif
 
-/*
-#define MOUNT_PROGRAM          100005
-#define MOUNT_VERSION          1
-#define MOUNT_MNT              1
-#define MOUNT_UMNT             3
- */
-
-static struct rpc_clnt *       mnt_create(char *, struct sockaddr_in *,
-                                                               int, int);
 static struct rpc_program      mnt_program;
 
 struct mnt_fhstatus {
-       unsigned int            status;
-       struct nfs_fh *         fh;
+       u32 status;
+       struct nfs_fh *fh;
 };
 
-/*
- * Obtain an NFS file handle for the given host and path
+/**
+ * nfs_mount - Obtain an NFS file handle for the given host and path
+ * @addr: pointer to server's address
+ * @len: size of server's address
+ * @hostname: name of server host, or NULL
+ * @path: pointer to string containing export path to mount
+ * @version: mount version to use for this request
+ * @protocol: transport protocol to use for thie request
+ * @fh: pointer to location to place returned file handle
+ *
+ * Uses default timeout parameters specified by underlying transport.
  */
-int
-nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
-               int version, int protocol)
+int nfs_mount(struct sockaddr *addr, size_t len, char *hostname, char *path,
+             int version, int protocol, struct nfs_fh *fh)
 {
-       struct rpc_clnt         *mnt_clnt;
        struct mnt_fhstatus     result = {
                .fh             = fh
        };
@@ -52,16 +48,25 @@ nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
                .rpc_argp       = path,
                .rpc_resp       = &result,
        };
-       char                    hostname[32];
+       struct rpc_create_args args = {
+               .protocol       = protocol,
+               .address        = addr,
+               .addrsize       = len,
+               .servername     = hostname,
+               .program        = &mnt_program,
+               .version        = version,
+               .authflavor     = RPC_AUTH_UNIX,
+               .flags          = RPC_CLNT_CREATE_INTR,
+       };
+       struct rpc_clnt         *mnt_clnt;
        int                     status;
 
-       dprintk("NFS:      nfs_mount(%08x:%s)\n",
-                       (unsigned)ntohl(addr->sin_addr.s_addr), path);
+       dprintk("NFS: sending MNT request for %s:%s\n",
+               (hostname ? hostname : "server"), path);
 
-       sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr->sin_addr.s_addr));
-       mnt_clnt = mnt_create(hostname, addr, version, protocol);
+       mnt_clnt = rpc_create(&args);
        if (IS_ERR(mnt_clnt))
-               return PTR_ERR(mnt_clnt);
+               goto out_clnt_err;
 
        if (version == NFS_MNT3_VERSION)
                msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT];
@@ -69,33 +74,39 @@ nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
                msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT];
 
        status = rpc_call_sync(mnt_clnt, &msg, 0);
-       return status < 0? status : (result.status? -EACCES : 0);
-}
+       rpc_shutdown_client(mnt_clnt);
 
-static struct rpc_clnt *
-mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version,
-               int protocol)
-{
-       struct rpc_create_args args = {
-               .protocol       = protocol,
-               .address        = (struct sockaddr *)srvaddr,
-               .addrsize       = sizeof(*srvaddr),
-               .servername     = hostname,
-               .program        = &mnt_program,
-               .version        = version,
-               .authflavor     = RPC_AUTH_UNIX,
-               .flags          = (RPC_CLNT_CREATE_ONESHOT |
-                                  RPC_CLNT_CREATE_INTR),
-       };
+       if (status < 0)
+               goto out_call_err;
+       if (result.status != 0)
+               goto out_mnt_err;
+
+       dprintk("NFS: MNT request succeeded\n");
+       status = 0;
+
+out:
+       return status;
+
+out_clnt_err:
+       status = PTR_ERR(mnt_clnt);
+       dprintk("NFS: failed to create RPC client, status=%d\n", status);
+       goto out;
+
+out_call_err:
+       dprintk("NFS: failed to start MNT request, status=%d\n", status);
+       goto out;
 
-       return rpc_create(&args);
+out_mnt_err:
+       dprintk("NFS: MNT server returned result %d\n", result.status);
+       status = -EACCES;
+       goto out;
 }
 
 /*
  * XDR encode/decode functions for MOUNT
  */
-static int
-xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p, const char *path)
+static int xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p,
+                             const char *path)
 {
        p = xdr_encode_string(p, path);
 
@@ -103,8 +114,8 @@ xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p, const char *path)
        return 0;
 }
 
-static int
-xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
+static int xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p,
+                              struct mnt_fhstatus *res)
 {
        struct nfs_fh *fh = res->fh;
 
@@ -115,8 +126,8 @@ xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
        return 0;
 }
 
-static int
-xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
+static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
+                               struct mnt_fhstatus *res)
 {
        struct nfs_fh *fh = res->fh;
 
@@ -135,53 +146,53 @@ xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
 #define MNT_fhstatus_sz                (1 + 8)
 #define MNT_fhstatus3_sz       (1 + 16)
 
-static struct rpc_procinfo     mnt_procedures[] = {
-[MNTPROC_MNT] = {
-         .p_proc               = MNTPROC_MNT,
-         .p_encode             = (kxdrproc_t) xdr_encode_dirpath,      
-         .p_decode             = (kxdrproc_t) xdr_decode_fhstatus,
-         .p_arglen             = MNT_dirpath_sz,
-         .p_replen             = MNT_fhstatus_sz,
-         .p_statidx            = MNTPROC_MNT,
-         .p_name               = "MOUNT",
+static struct rpc_procinfo mnt_procedures[] = {
+       [MNTPROC_MNT] = {
+               .p_proc         = MNTPROC_MNT,
+               .p_encode       = (kxdrproc_t) xdr_encode_dirpath,
+               .p_decode       = (kxdrproc_t) xdr_decode_fhstatus,
+               .p_arglen       = MNT_dirpath_sz,
+               .p_replen       = MNT_fhstatus_sz,
+               .p_statidx      = MNTPROC_MNT,
+               .p_name         = "MOUNT",
        },
 };
 
 static struct rpc_procinfo mnt3_procedures[] = {
-[MOUNTPROC3_MNT] = {
-         .p_proc               = MOUNTPROC3_MNT,
-         .p_encode             = (kxdrproc_t) xdr_encode_dirpath,
-         .p_decode             = (kxdrproc_t) xdr_decode_fhstatus3,
-         .p_arglen             = MNT_dirpath_sz,
-         .p_replen             = MNT_fhstatus3_sz,
-         .p_statidx            = MOUNTPROC3_MNT,
-         .p_name               = "MOUNT",
+       [MOUNTPROC3_MNT] = {
+               .p_proc         = MOUNTPROC3_MNT,
+               .p_encode       = (kxdrproc_t) xdr_encode_dirpath,
+               .p_decode       = (kxdrproc_t) xdr_decode_fhstatus3,
+               .p_arglen       = MNT_dirpath_sz,
+               .p_replen       = MNT_fhstatus3_sz,
+               .p_statidx      = MOUNTPROC3_MNT,
+               .p_name         = "MOUNT",
        },
 };
 
 
-static struct rpc_version      mnt_version1 = {
-               .number         = 1,
-               .nrprocs        = 2,
-               .procs          = mnt_procedures
+static struct rpc_version mnt_version1 = {
+       .number         = 1,
+       .nrprocs        = 2,
+       .procs          = mnt_procedures,
 };
 
-static struct rpc_version       mnt_version3 = {
-               .number         = 3,
-               .nrprocs        = 2,
-               .procs          = mnt3_procedures
+static struct rpc_version mnt_version3 = {
+       .number         = 3,
+       .nrprocs        = 2,
+       .procs          = mnt3_procedures,
 };
 
-static struct rpc_version *    mnt_version[] = {
+static struct rpc_version *mnt_version[] = {
        NULL,
        &mnt_version1,
        NULL,
        &mnt_version3,
 };
 
-static struct rpc_stat         mnt_stats;
+static struct rpc_stat mnt_stats;
 
-static struct rpc_program      mnt_program = {
+static struct rpc_program mnt_program = {
        .name           = "mount",
        .number         = NFS_MNT_PROGRAM,
        .nrvers         = ARRAY_SIZE(mnt_version),
index cd3ca7b5d3dbfd0dda765505fe086f7288f37d32..7fcc78f2aa71562ffaf820518b4ae718f3fdf415 100644 (file)
@@ -223,7 +223,7 @@ nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
 static int
 nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
 {
-       struct rpc_auth *auth = req->rq_task->tk_auth;
+       struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
        unsigned int replen;
        u32 offset = (u32)args->offset;
        u32 count = args->count;
@@ -380,7 +380,7 @@ static int
 nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args)
 {
        struct rpc_task *task = req->rq_task;
-       struct rpc_auth *auth = task->tk_auth;
+       struct rpc_auth *auth = task->tk_msg.rpc_cred->cr_auth;
        unsigned int replen;
        u32 count = args->count;
 
@@ -541,7 +541,7 @@ nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
 static int
 nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args)
 {
-       struct rpc_auth *auth = req->rq_task->tk_auth;
+       struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
        unsigned int replen;
 
        p = xdr_encode_fhandle(p, args->fh);
index 45268d6def2eda4c9d286ba048ba058156924e87..814d886b6aa4205e8f634451161f291eaa48e10a 100644 (file)
@@ -335,9 +335,7 @@ again:
                 * not sure this buys us anything (and I'd have
                 * to revamp the NFSv3 XDR code) */
                status = nfs3_proc_setattr(dentry, &fattr, sattr);
-               if (status == 0)
-                       nfs_setattr_update_inode(dentry->d_inode, sattr);
-               nfs_refresh_inode(dentry->d_inode, &fattr);
+               nfs_post_op_update_inode(dentry->d_inode, &fattr);
                dprintk("NFS reply setattr (post-create): %d\n", status);
        }
        if (status != 0)
index b51df8eb9f010c070ec4545248374fa02687e175..b4647a22f349273287954f9c3028cd227324d023 100644 (file)
@@ -319,7 +319,7 @@ nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *arg
 static int
 nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
 {
-       struct rpc_auth *auth = req->rq_task->tk_auth;
+       struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
        unsigned int replen;
        u32 count = args->count;
 
@@ -458,7 +458,7 @@ nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args)
 static int
 nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
 {
-       struct rpc_auth *auth = req->rq_task->tk_auth;
+       struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
        unsigned int replen;
        u32 count = args->count;
 
@@ -643,7 +643,7 @@ static int
 nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
                    struct nfs3_getaclargs *args)
 {
-       struct rpc_auth *auth = req->rq_task->tk_auth;
+       struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
        unsigned int replen;
 
        p = xdr_encode_fhandle(p, args->fh);
@@ -773,7 +773,7 @@ nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
 static int
 nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
 {
-       struct rpc_auth *auth = req->rq_task->tk_auth;
+       struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
        unsigned int replen;
 
        p = xdr_encode_fhandle(p, args->fh);
index cf3a17eb5c09e0ec5e88e97fd078ab872b092457..6c028e734fe678ad5880fe6dc308dc47957e34e3 100644 (file)
@@ -70,19 +70,26 @@ static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status
                seqid->flags |= NFS_SEQID_CONFIRMED;
 }
 
+struct nfs_unique_id {
+       struct rb_node rb_node;
+       __u64 id;
+};
+
 /*
  * NFS4 state_owners and lock_owners are simply labels for ordered
  * sequences of RPC calls. Their sole purpose is to provide once-only
  * semantics by allowing the server to identify replayed requests.
  */
 struct nfs4_state_owner {
-       spinlock_t           so_lock;
-       struct list_head     so_list;    /* per-clientid list of state_owners */
+       struct nfs_unique_id so_owner_id;
        struct nfs_client    *so_client;
-       u32                  so_id;      /* 32-bit identifier, unique */
-       atomic_t             so_count;
+       struct nfs_server    *so_server;
+       struct rb_node       so_client_node;
 
        struct rpc_cred      *so_cred;   /* Associated cred */
+
+       spinlock_t           so_lock;
+       atomic_t             so_count;
        struct list_head     so_states;
        struct list_head     so_delegations;
        struct nfs_seqid_counter so_seqid;
@@ -108,7 +115,7 @@ struct nfs4_lock_state {
 #define NFS_LOCK_INITIALIZED 1
        int                     ls_flags;
        struct nfs_seqid_counter        ls_seqid;
-       u32                     ls_id;
+       struct nfs_unique_id    ls_id;
        nfs4_stateid            ls_stateid;
        atomic_t                ls_count;
 };
@@ -116,7 +123,10 @@ struct nfs4_lock_state {
 /* bits for nfs4_state->flags */
 enum {
        LK_STATE_IN_USE,
-       NFS_DELEGATED_STATE,
+       NFS_DELEGATED_STATE,            /* Current stateid is delegation */
+       NFS_O_RDONLY_STATE,             /* OPEN stateid has read-only state */
+       NFS_O_WRONLY_STATE,             /* OPEN stateid has write-only state */
+       NFS_O_RDWR_STATE,               /* OPEN stateid has read/write state */
 };
 
 struct nfs4_state {
@@ -130,11 +140,14 @@ struct nfs4_state {
        unsigned long flags;            /* Do we hold any locks? */
        spinlock_t state_lock;          /* Protects the lock_states list */
 
-       nfs4_stateid stateid;
+       seqlock_t seqlock;              /* Protects the stateid/open_stateid */
+       nfs4_stateid stateid;           /* Current stateid: may be delegation */
+       nfs4_stateid open_stateid;      /* OPEN stateid */
 
-       unsigned int n_rdonly;
-       unsigned int n_wronly;
-       unsigned int n_rdwr;
+       /* The following 3 fields are protected by owner->so_lock */
+       unsigned int n_rdonly;          /* Number of read-only references */
+       unsigned int n_wronly;          /* Number of write-only references */
+       unsigned int n_rdwr;            /* Number of read/write references */
        int state;                      /* State on the server (R,W, or RW) */
        atomic_t count;
 };
@@ -165,7 +178,7 @@ extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struc
 extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
-extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state);
+extern int nfs4_do_close(struct path *path, struct nfs4_state *state);
 extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
@@ -189,14 +202,13 @@ extern void nfs4_renew_state(struct work_struct *);
 
 /* nfs4state.c */
 struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp);
-extern u32 nfs4_alloc_lockowner_id(struct nfs_client *);
 
 extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
 extern void nfs4_put_state_owner(struct nfs4_state_owner *);
 extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
 extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
 extern void nfs4_put_open_state(struct nfs4_state *);
-extern void nfs4_close_state(struct nfs4_state *, mode_t);
+extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t);
 extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t);
 extern void nfs4_schedule_state_recovery(struct nfs_client *);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
@@ -222,7 +234,7 @@ extern struct svc_version nfs4_callback_version1;
 
 #else
 
-#define nfs4_close_state(a, b) do { } while (0)
+#define nfs4_close_state(a, b, c) do { } while (0)
 
 #endif /* CONFIG_NFS_V4 */
 #endif /* __LINUX_FS_NFS_NFS4_FS.H */
index 648e0ac0f90ea07aa74e8f1da5610c30392490ce..fee2da856c953028eec1a2818e84221f1681704f 100644 (file)
@@ -65,6 +65,7 @@ static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *)
 static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
 static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
 static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp);
+static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags);
 
 /* Prevent leaks of NFSv4 errors into userland */
 int nfs4_map_errors(int err)
@@ -214,27 +215,39 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
 }
 
 struct nfs4_opendata {
-       atomic_t count;
+       struct kref kref;
        struct nfs_openargs o_arg;
        struct nfs_openres o_res;
        struct nfs_open_confirmargs c_arg;
        struct nfs_open_confirmres c_res;
        struct nfs_fattr f_attr;
        struct nfs_fattr dir_attr;
-       struct dentry *dentry;
+       struct path path;
        struct dentry *dir;
        struct nfs4_state_owner *owner;
+       struct nfs4_state *state;
        struct iattr attrs;
        unsigned long timestamp;
+       unsigned int rpc_done : 1;
        int rpc_status;
        int cancelled;
 };
 
-static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
+
+static void nfs4_init_opendata_res(struct nfs4_opendata *p)
+{
+       p->o_res.f_attr = &p->f_attr;
+       p->o_res.dir_attr = &p->dir_attr;
+       p->o_res.server = p->o_arg.server;
+       nfs_fattr_init(&p->f_attr);
+       nfs_fattr_init(&p->dir_attr);
+}
+
+static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
                struct nfs4_state_owner *sp, int flags,
                const struct iattr *attrs)
 {
-       struct dentry *parent = dget_parent(dentry);
+       struct dentry *parent = dget_parent(path->dentry);
        struct inode *dir = parent->d_inode;
        struct nfs_server *server = NFS_SERVER(dir);
        struct nfs4_opendata *p;
@@ -245,24 +258,19 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
        p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
        if (p->o_arg.seqid == NULL)
                goto err_free;
-       atomic_set(&p->count, 1);
-       p->dentry = dget(dentry);
+       p->path.mnt = mntget(path->mnt);
+       p->path.dentry = dget(path->dentry);
        p->dir = parent;
        p->owner = sp;
        atomic_inc(&sp->so_count);
        p->o_arg.fh = NFS_FH(dir);
        p->o_arg.open_flags = flags,
        p->o_arg.clientid = server->nfs_client->cl_clientid;
-       p->o_arg.id = sp->so_id;
-       p->o_arg.name = &dentry->d_name;
+       p->o_arg.id = sp->so_owner_id.id;
+       p->o_arg.name = &p->path.dentry->d_name;
        p->o_arg.server = server;
        p->o_arg.bitmask = server->attr_bitmask;
        p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
-       p->o_res.f_attr = &p->f_attr;
-       p->o_res.dir_attr = &p->dir_attr;
-       p->o_res.server = server;
-       nfs_fattr_init(&p->f_attr);
-       nfs_fattr_init(&p->dir_attr);
        if (flags & O_EXCL) {
                u32 *s = (u32 *) p->o_arg.u.verifier.data;
                s[0] = jiffies;
@@ -274,6 +282,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
        p->c_arg.fh = &p->o_res.fh;
        p->c_arg.stateid = &p->o_res.stateid;
        p->c_arg.seqid = p->o_arg.seqid;
+       nfs4_init_opendata_res(p);
+       kref_init(&p->kref);
        return p;
 err_free:
        kfree(p);
@@ -282,27 +292,25 @@ err:
        return NULL;
 }
 
-static void nfs4_opendata_free(struct nfs4_opendata *p)
+static void nfs4_opendata_free(struct kref *kref)
 {
-       if (p != NULL && atomic_dec_and_test(&p->count)) {
-               nfs_free_seqid(p->o_arg.seqid);
-               nfs4_put_state_owner(p->owner);
-               dput(p->dir);
-               dput(p->dentry);
-               kfree(p);
-       }
+       struct nfs4_opendata *p = container_of(kref,
+                       struct nfs4_opendata, kref);
+
+       nfs_free_seqid(p->o_arg.seqid);
+       if (p->state != NULL)
+               nfs4_put_open_state(p->state);
+       nfs4_put_state_owner(p->owner);
+       dput(p->dir);
+       dput(p->path.dentry);
+       mntput(p->path.mnt);
+       kfree(p);
 }
 
-/* Helper for asynchronous RPC calls */
-static int nfs4_call_async(struct rpc_clnt *clnt,
-               const struct rpc_call_ops *tk_ops, void *calldata)
+static void nfs4_opendata_put(struct nfs4_opendata *p)
 {
-       struct rpc_task *task;
-
-       if (!(task = rpc_new_task(clnt, RPC_TASK_ASYNC, tk_ops, calldata)))
-               return -ENOMEM;
-       rpc_execute(task);
-       return 0;
+       if (p != NULL)
+               kref_put(&p->kref, nfs4_opendata_free);
 }
 
 static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
@@ -316,7 +324,34 @@ static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
        return ret;
 }
 
-static inline void update_open_stateflags(struct nfs4_state *state, mode_t open_flags)
+static int can_open_cached(struct nfs4_state *state, int mode)
+{
+       int ret = 0;
+       switch (mode & (FMODE_READ|FMODE_WRITE|O_EXCL)) {
+               case FMODE_READ:
+                       ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0;
+                       ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
+                       break;
+               case FMODE_WRITE:
+                       ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0;
+                       ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
+                       break;
+               case FMODE_READ|FMODE_WRITE:
+                       ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
+       }
+       return ret;
+}
+
+static int can_open_delegated(struct nfs_delegation *delegation, mode_t open_flags)
+{
+       if ((delegation->type & open_flags) != open_flags)
+               return 0;
+       if (delegation->flags & NFS_DELEGATION_NEED_RECLAIM)
+               return 0;
+       return 1;
+}
+
+static void update_open_stateflags(struct nfs4_state *state, mode_t open_flags)
 {
        switch (open_flags) {
                case FMODE_WRITE:
@@ -328,41 +363,176 @@ static inline void update_open_stateflags(struct nfs4_state *state, mode_t open_
                case FMODE_READ|FMODE_WRITE:
                        state->n_rdwr++;
        }
+       nfs4_state_set_mode_locked(state, state->state | open_flags);
 }
 
-static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
+static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
 {
-       struct inode *inode = state->inode;
+       if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
+               memcpy(state->stateid.data, stateid->data, sizeof(state->stateid.data));
+       memcpy(state->open_stateid.data, stateid->data, sizeof(state->open_stateid.data));
+       switch (open_flags) {
+               case FMODE_READ:
+                       set_bit(NFS_O_RDONLY_STATE, &state->flags);
+                       break;
+               case FMODE_WRITE:
+                       set_bit(NFS_O_WRONLY_STATE, &state->flags);
+                       break;
+               case FMODE_READ|FMODE_WRITE:
+                       set_bit(NFS_O_RDWR_STATE, &state->flags);
+       }
+}
+
+static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
+{
+       write_seqlock(&state->seqlock);
+       nfs_set_open_stateid_locked(state, stateid, open_flags);
+       write_sequnlock(&state->seqlock);
+}
 
+static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *deleg_stateid, int open_flags)
+{
        open_flags &= (FMODE_READ|FMODE_WRITE);
-       /* Protect against nfs4_find_state_byowner() */
+       /*
+        * Protect the call to nfs4_state_set_mode_locked and
+        * serialise the stateid update
+        */
+       write_seqlock(&state->seqlock);
+       if (deleg_stateid != NULL) {
+               memcpy(state->stateid.data, deleg_stateid->data, sizeof(state->stateid.data));
+               set_bit(NFS_DELEGATED_STATE, &state->flags);
+       }
+       if (open_stateid != NULL)
+               nfs_set_open_stateid_locked(state, open_stateid, open_flags);
+       write_sequnlock(&state->seqlock);
        spin_lock(&state->owner->so_lock);
-       spin_lock(&inode->i_lock);
-       memcpy(&state->stateid, stateid, sizeof(state->stateid));
        update_open_stateflags(state, open_flags);
-       nfs4_state_set_mode_locked(state, state->state | open_flags);
-       spin_unlock(&inode->i_lock);
        spin_unlock(&state->owner->so_lock);
 }
 
+static void nfs4_return_incompatible_delegation(struct inode *inode, mode_t open_flags)
+{
+       struct nfs_delegation *delegation;
+
+       rcu_read_lock();
+       delegation = rcu_dereference(NFS_I(inode)->delegation);
+       if (delegation == NULL || (delegation->type & open_flags) == open_flags) {
+               rcu_read_unlock();
+               return;
+       }
+       rcu_read_unlock();
+       nfs_inode_return_delegation(inode);
+}
+
+static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
+{
+       struct nfs4_state *state = opendata->state;
+       struct nfs_inode *nfsi = NFS_I(state->inode);
+       struct nfs_delegation *delegation;
+       int open_mode = opendata->o_arg.open_flags & (FMODE_READ|FMODE_WRITE|O_EXCL);
+       nfs4_stateid stateid;
+       int ret = -EAGAIN;
+
+       rcu_read_lock();
+       delegation = rcu_dereference(nfsi->delegation);
+       for (;;) {
+               if (can_open_cached(state, open_mode)) {
+                       spin_lock(&state->owner->so_lock);
+                       if (can_open_cached(state, open_mode)) {
+                               update_open_stateflags(state, open_mode);
+                               spin_unlock(&state->owner->so_lock);
+                               rcu_read_unlock();
+                               goto out_return_state;
+                       }
+                       spin_unlock(&state->owner->so_lock);
+               }
+               if (delegation == NULL)
+                       break;
+               if (!can_open_delegated(delegation, open_mode))
+                       break;
+               /* Save the delegation */
+               memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data));
+               rcu_read_unlock();
+               lock_kernel();
+               ret = _nfs4_do_access(state->inode, state->owner->so_cred, open_mode);
+               unlock_kernel();
+               if (ret != 0)
+                       goto out;
+               ret = -EAGAIN;
+               rcu_read_lock();
+               delegation = rcu_dereference(nfsi->delegation);
+               /* If no delegation, try a cached open */
+               if (delegation == NULL)
+                       continue;
+               /* Is the delegation still valid? */
+               if (memcmp(stateid.data, delegation->stateid.data, sizeof(stateid.data)) != 0)
+                       continue;
+               rcu_read_unlock();
+               update_open_stateid(state, NULL, &stateid, open_mode);
+               goto out_return_state;
+       }
+       rcu_read_unlock();
+out:
+       return ERR_PTR(ret);
+out_return_state:
+       atomic_inc(&state->count);
+       return state;
+}
+
 static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
 {
        struct inode *inode;
        struct nfs4_state *state = NULL;
+       struct nfs_delegation *delegation;
+       nfs4_stateid *deleg_stateid = NULL;
+       int ret;
 
-       if (!(data->f_attr.valid & NFS_ATTR_FATTR))
+       if (!data->rpc_done) {
+               state = nfs4_try_open_cached(data);
                goto out;
+       }
+
+       ret = -EAGAIN;
+       if (!(data->f_attr.valid & NFS_ATTR_FATTR))
+               goto err;
        inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr);
+       ret = PTR_ERR(inode);
        if (IS_ERR(inode))
-               goto out;
+               goto err;
+       ret = -ENOMEM;
        state = nfs4_get_open_state(inode, data->owner);
        if (state == NULL)
-               goto put_inode;
-       update_open_stateid(state, &data->o_res.stateid, data->o_arg.open_flags);
-put_inode:
+               goto err_put_inode;
+       if (data->o_res.delegation_type != 0) {
+               int delegation_flags = 0;
+
+               rcu_read_lock();
+               delegation = rcu_dereference(NFS_I(inode)->delegation);
+               if (delegation)
+                       delegation_flags = delegation->flags;
+               rcu_read_unlock();
+               if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM))
+                       nfs_inode_set_delegation(state->inode,
+                                       data->owner->so_cred,
+                                       &data->o_res);
+               else
+                       nfs_inode_reclaim_delegation(state->inode,
+                                       data->owner->so_cred,
+                                       &data->o_res);
+       }
+       rcu_read_lock();
+       delegation = rcu_dereference(NFS_I(inode)->delegation);
+       if (delegation != NULL)
+               deleg_stateid = &delegation->stateid;
+       update_open_stateid(state, &data->o_res.stateid, deleg_stateid, data->o_arg.open_flags);
+       rcu_read_unlock();
        iput(inode);
 out:
        return state;
+err_put_inode:
+       iput(inode);
+err:
+       return ERR_PTR(ret);
 }
 
 static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state)
@@ -382,79 +552,66 @@ static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *
        return ERR_PTR(-ENOENT);
 }
 
-static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, nfs4_stateid *stateid)
+static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res)
 {
+       struct nfs4_state *newstate;
        int ret;
 
        opendata->o_arg.open_flags = openflags;
+       memset(&opendata->o_res, 0, sizeof(opendata->o_res));
+       memset(&opendata->c_res, 0, sizeof(opendata->c_res));
+       nfs4_init_opendata_res(opendata);
        ret = _nfs4_proc_open(opendata);
        if (ret != 0)
                return ret; 
-       memcpy(stateid->data, opendata->o_res.stateid.data,
-                       sizeof(stateid->data));
+       newstate = nfs4_opendata_to_nfs4_state(opendata);
+       if (IS_ERR(newstate))
+               return PTR_ERR(newstate);
+       nfs4_close_state(&opendata->path, newstate, openflags);
+       *res = newstate;
        return 0;
 }
 
 static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state)
 {
-       nfs4_stateid stateid;
        struct nfs4_state *newstate;
-       int mode = 0;
-       int delegation = 0;
        int ret;
 
        /* memory barrier prior to reading state->n_* */
+       clear_bit(NFS_DELEGATED_STATE, &state->flags);
        smp_rmb();
        if (state->n_rdwr != 0) {
-               ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &stateid);
+               ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
                if (ret != 0)
                        return ret;
-               mode |= FMODE_READ|FMODE_WRITE;
-               if (opendata->o_res.delegation_type != 0)
-                       delegation = opendata->o_res.delegation_type;
-               smp_rmb();
+               if (newstate != state)
+                       return -ESTALE;
        }
        if (state->n_wronly != 0) {
-               ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &stateid);
+               ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
                if (ret != 0)
                        return ret;
-               mode |= FMODE_WRITE;
-               if (opendata->o_res.delegation_type != 0)
-                       delegation = opendata->o_res.delegation_type;
-               smp_rmb();
+               if (newstate != state)
+                       return -ESTALE;
        }
        if (state->n_rdonly != 0) {
-               ret = nfs4_open_recover_helper(opendata, FMODE_READ, &stateid);
+               ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
                if (ret != 0)
                        return ret;
-               mode |= FMODE_READ;
+               if (newstate != state)
+                       return -ESTALE;
        }
-       clear_bit(NFS_DELEGATED_STATE, &state->flags);
-       if (mode == 0)
-               return 0;
-       if (opendata->o_res.delegation_type == 0)
-               opendata->o_res.delegation_type = delegation;
-       opendata->o_arg.open_flags |= mode;
-       newstate = nfs4_opendata_to_nfs4_state(opendata);
-       if (newstate != NULL) {
-               if (opendata->o_res.delegation_type != 0) {
-                       struct nfs_inode *nfsi = NFS_I(newstate->inode);
-                       int delegation_flags = 0;
-                       if (nfsi->delegation)
-                               delegation_flags = nfsi->delegation->flags;
-                       if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM))
-                               nfs_inode_set_delegation(newstate->inode,
-                                               opendata->owner->so_cred,
-                                               &opendata->o_res);
-                       else
-                               nfs_inode_reclaim_delegation(newstate->inode,
-                                               opendata->owner->so_cred,
-                                               &opendata->o_res);
-               }
-               nfs4_close_state(newstate, opendata->o_arg.open_flags);
+       /*
+        * We may have performed cached opens for all three recoveries.
+        * Check if we need to update the current stateid.
+        */
+       if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0 &&
+           memcmp(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)) != 0) {
+               write_seqlock(&state->seqlock);
+               if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
+                       memcpy(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data));
+               write_sequnlock(&state->seqlock);
        }
-       if (newstate != state)
-               return -ESTALE;
        return 0;
 }
 
@@ -462,41 +619,37 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
  * OPEN_RECLAIM:
  *     reclaim state on the server after a reboot.
  */
-static int _nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
 {
-       struct nfs_delegation *delegation = NFS_I(state->inode)->delegation;
+       struct nfs_delegation *delegation;
        struct nfs4_opendata *opendata;
        int delegation_type = 0;
        int status;
 
-       if (delegation != NULL) {
-               if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
-                       memcpy(&state->stateid, &delegation->stateid,
-                                       sizeof(state->stateid));
-                       set_bit(NFS_DELEGATED_STATE, &state->flags);
-                       return 0;
-               }
-               delegation_type = delegation->type;
-       }
-       opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
+       opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
        if (opendata == NULL)
                return -ENOMEM;
        opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS;
        opendata->o_arg.fh = NFS_FH(state->inode);
        nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh);
+       rcu_read_lock();
+       delegation = rcu_dereference(NFS_I(state->inode)->delegation);
+       if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0)
+               delegation_type = delegation->flags;
+       rcu_read_unlock();
        opendata->o_arg.u.delegation_type = delegation_type;
        status = nfs4_open_recover(opendata, state);
-       nfs4_opendata_free(opendata);
+       nfs4_opendata_put(opendata);
        return status;
 }
 
-static int nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs4_exception exception = { };
        int err;
        do {
-               err = _nfs4_do_open_reclaim(sp, state, dentry);
+               err = _nfs4_do_open_reclaim(ctx, state);
                if (err != -NFS4ERR_DELAY)
                        break;
                nfs4_handle_exception(server, err, &exception);
@@ -512,37 +665,35 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
        ctx = nfs4_state_find_open_context(state);
        if (IS_ERR(ctx))
                return PTR_ERR(ctx);
-       ret = nfs4_do_open_reclaim(sp, state, ctx->dentry);
+       ret = nfs4_do_open_reclaim(ctx, state);
        put_nfs_open_context(ctx);
        return ret;
 }
 
-static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
+static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
 {
        struct nfs4_state_owner  *sp  = state->owner;
        struct nfs4_opendata *opendata;
        int ret;
 
-       if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
-               return 0;
-       opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
+       opendata = nfs4_opendata_alloc(&ctx->path, sp, 0, NULL);
        if (opendata == NULL)
                return -ENOMEM;
        opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
-       memcpy(opendata->o_arg.u.delegation.data, state->stateid.data,
+       memcpy(opendata->o_arg.u.delegation.data, stateid->data,
                        sizeof(opendata->o_arg.u.delegation.data));
        ret = nfs4_open_recover(opendata, state);
-       nfs4_opendata_free(opendata);
+       nfs4_opendata_put(opendata);
        return ret;
 }
 
-int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
 {
        struct nfs4_exception exception = { };
-       struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+       struct nfs_server *server = NFS_SERVER(state->inode);
        int err;
        do {
-               err = _nfs4_open_delegation_recall(dentry, state);
+               err = _nfs4_open_delegation_recall(ctx, state, stateid);
                switch (err) {
                        case 0:
                                return err;
@@ -582,9 +733,10 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
                memcpy(data->o_res.stateid.data, data->c_res.stateid.data,
                                sizeof(data->o_res.stateid.data));
                renew_lease(data->o_res.server, data->timestamp);
+               data->rpc_done = 1;
        }
-       nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
        nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status);
+       nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
 }
 
 static void nfs4_open_confirm_release(void *calldata)
@@ -596,14 +748,14 @@ static void nfs4_open_confirm_release(void *calldata)
        if (data->cancelled == 0)
                goto out_free;
        /* In case of error, no cleanup! */
-       if (data->rpc_status != 0)
+       if (!data->rpc_done)
                goto out_free;
        nfs_confirm_seqid(&data->owner->so_seqid, 0);
        state = nfs4_opendata_to_nfs4_state(data);
-       if (state != NULL)
-               nfs4_close_state(state, data->o_arg.open_flags);
+       if (!IS_ERR(state))
+               nfs4_close_state(&data->path, state, data->o_arg.open_flags);
 out_free:
-       nfs4_opendata_free(data);
+       nfs4_opendata_put(data);
 }
 
 static const struct rpc_call_ops nfs4_open_confirm_ops = {
@@ -621,12 +773,9 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
        struct rpc_task *task;
        int status;
 
-       atomic_inc(&data->count);
-       /*
-        * If rpc_run_task() ends up calling ->rpc_release(), we
-        * want to ensure that it takes the 'error' code path.
-        */
-       data->rpc_status = -ENOMEM;
+       kref_get(&data->kref);
+       data->rpc_done = 0;
+       data->rpc_status = 0;
        task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data);
        if (IS_ERR(task))
                return PTR_ERR(task);
@@ -653,13 +802,35 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
        
        if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0)
                return;
+       /*
+        * Check if we still need to send an OPEN call, or if we can use
+        * a delegation instead.
+        */
+       if (data->state != NULL) {
+               struct nfs_delegation *delegation;
+
+               if (can_open_cached(data->state, data->o_arg.open_flags & (FMODE_READ|FMODE_WRITE|O_EXCL)))
+                       goto out_no_action;
+               rcu_read_lock();
+               delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
+               if (delegation != NULL &&
+                  (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0) {
+                       rcu_read_unlock();
+                       goto out_no_action;
+               }
+               rcu_read_unlock();
+       }
        /* Update sequence id. */
-       data->o_arg.id = sp->so_id;
+       data->o_arg.id = sp->so_owner_id.id;
        data->o_arg.clientid = sp->so_client->cl_clientid;
        if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS)
                msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
        data->timestamp = jiffies;
        rpc_call_setup(task, &msg, 0);
+       return;
+out_no_action:
+       task->tk_action = NULL;
+
 }
 
 static void nfs4_open_done(struct rpc_task *task, void *calldata)
@@ -683,8 +854,11 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
                                data->rpc_status = -ENOTDIR;
                }
                renew_lease(data->o_res.server, data->timestamp);
+               if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
+                       nfs_confirm_seqid(&data->owner->so_seqid, 0);
        }
        nfs_increment_open_seqid(data->rpc_status, data->o_arg.seqid);
+       data->rpc_done = 1;
 }
 
 static void nfs4_open_release(void *calldata)
@@ -696,17 +870,17 @@ static void nfs4_open_release(void *calldata)
        if (data->cancelled == 0)
                goto out_free;
        /* In case of error, no cleanup! */
-       if (data->rpc_status != 0)
+       if (data->rpc_status != 0 || !data->rpc_done)
                goto out_free;
        /* In case we need an open_confirm, no cleanup! */
        if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
                goto out_free;
        nfs_confirm_seqid(&data->owner->so_seqid, 0);
        state = nfs4_opendata_to_nfs4_state(data);
-       if (state != NULL)
-               nfs4_close_state(state, data->o_arg.open_flags);
+       if (!IS_ERR(state))
+               nfs4_close_state(&data->path, state, data->o_arg.open_flags);
 out_free:
-       nfs4_opendata_free(data);
+       nfs4_opendata_put(data);
 }
 
 static const struct rpc_call_ops nfs4_open_ops = {
@@ -727,12 +901,10 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
        struct rpc_task *task;
        int status;
 
-       atomic_inc(&data->count);
-       /*
-        * If rpc_run_task() ends up calling ->rpc_release(), we
-        * want to ensure that it takes the 'error' code path.
-        */
-       data->rpc_status = -ENOMEM;
+       kref_get(&data->kref);
+       data->rpc_done = 0;
+       data->rpc_status = 0;
+       data->cancelled = 0;
        task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data);
        if (IS_ERR(task))
                return PTR_ERR(task);
@@ -743,7 +915,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
        } else
                status = data->rpc_status;
        rpc_put_task(task);
-       if (status != 0)
+       if (status != 0 || !data->rpc_done)
                return status;
 
        if (o_arg->open_flags & O_CREAT) {
@@ -756,7 +928,6 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
                if (status != 0)
                        return status;
        }
-       nfs_confirm_seqid(&data->owner->so_seqid, 0);
        if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
                return server->nfs_client->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
        return 0;
@@ -772,6 +943,8 @@ static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openf
                mask |= MAY_READ;
        if (openflags & FMODE_WRITE)
                mask |= MAY_WRITE;
+       if (openflags & FMODE_EXEC)
+               mask |= MAY_EXEC;
        status = nfs_access_get_cached(inode, cred, &cache);
        if (status == 0)
                goto out;
@@ -811,43 +984,32 @@ static int nfs4_recover_expired_lease(struct nfs_server *server)
  *     reclaim state on the server after a network partition.
  *     Assumes caller holds the appropriate lock
  */
-static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
 {
-       struct inode *inode = state->inode;
-       struct nfs_delegation *delegation = NFS_I(inode)->delegation;
        struct nfs4_opendata *opendata;
-       int openflags = state->state & (FMODE_READ|FMODE_WRITE);
        int ret;
 
-       if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
-               ret = _nfs4_do_access(inode, sp->so_cred, openflags);
-               if (ret < 0)
-                       return ret;
-               memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
-               set_bit(NFS_DELEGATED_STATE, &state->flags);
-               return 0;
-       }
-       opendata = nfs4_opendata_alloc(dentry, sp, openflags, NULL);
+       opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
        if (opendata == NULL)
                return -ENOMEM;
        ret = nfs4_open_recover(opendata, state);
        if (ret == -ESTALE) {
                /* Invalidate the state owner so we don't ever use it again */
-               nfs4_drop_state_owner(sp);
-               d_drop(dentry);
+               nfs4_drop_state_owner(state->owner);
+               d_drop(ctx->path.dentry);
        }
-       nfs4_opendata_free(opendata);
+       nfs4_opendata_put(opendata);
        return ret;
 }
 
-static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
 {
-       struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+       struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs4_exception exception = { };
        int err;
 
        do {
-               err = _nfs4_open_expired(sp, state, dentry);
+               err = _nfs4_open_expired(ctx, state);
                if (err == -NFS4ERR_DELAY)
                        nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
@@ -862,107 +1024,38 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
        ctx = nfs4_state_find_open_context(state);
        if (IS_ERR(ctx))
                return PTR_ERR(ctx);
-       ret = nfs4_do_open_expired(sp, state, ctx->dentry);
+       ret = nfs4_do_open_expired(ctx, state);
        put_nfs_open_context(ctx);
        return ret;
 }
 
 /*
- * Returns a referenced nfs4_state if there is an open delegation on the file
+ * on an EXCLUSIVE create, the server should send back a bitmask with FATTR4-*
+ * fields corresponding to attributes that were used to store the verifier.
+ * Make sure we clobber those fields in the later setattr call
  */
-static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
-{
-       struct nfs_delegation *delegation;
-       struct nfs_server *server = NFS_SERVER(inode);
-       struct nfs_client *clp = server->nfs_client;
-       struct nfs_inode *nfsi = NFS_I(inode);
-       struct nfs4_state_owner *sp = NULL;
-       struct nfs4_state *state = NULL;
-       int open_flags = flags & (FMODE_READ|FMODE_WRITE);
-       int err;
-
-       err = -ENOMEM;
-       if (!(sp = nfs4_get_state_owner(server, cred))) {
-               dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
-               return err;
-       }
-       err = nfs4_recover_expired_lease(server);
-       if (err != 0)
-               goto out_put_state_owner;
-       /* Protect against reboot recovery - NOTE ORDER! */
-       down_read(&clp->cl_sem);
-       /* Protect against delegation recall */
-       down_read(&nfsi->rwsem);
-       delegation = NFS_I(inode)->delegation;
-       err = -ENOENT;
-       if (delegation == NULL || (delegation->type & open_flags) != open_flags)
-               goto out_err;
-       err = -ENOMEM;
-       state = nfs4_get_open_state(inode, sp);
-       if (state == NULL)
-               goto out_err;
-
-       err = -ENOENT;
-       if ((state->state & open_flags) == open_flags) {
-               spin_lock(&inode->i_lock);
-               update_open_stateflags(state, open_flags);
-               spin_unlock(&inode->i_lock);
-               goto out_ok;
-       } else if (state->state != 0)
-               goto out_put_open_state;
-
-       lock_kernel();
-       err = _nfs4_do_access(inode, cred, open_flags);
-       unlock_kernel();
-       if (err != 0)
-               goto out_put_open_state;
-       set_bit(NFS_DELEGATED_STATE, &state->flags);
-       update_open_stateid(state, &delegation->stateid, open_flags);
-out_ok:
-       nfs4_put_state_owner(sp);
-       up_read(&nfsi->rwsem);
-       up_read(&clp->cl_sem);
-       *res = state;
-       return 0;
-out_put_open_state:
-       nfs4_put_open_state(state);
-out_err:
-       up_read(&nfsi->rwsem);
-       up_read(&clp->cl_sem);
-       if (err != -EACCES)
-               nfs_inode_return_delegation(inode);
-out_put_state_owner:
-       nfs4_put_state_owner(sp);
-       return err;
-}
-
-static struct nfs4_state *nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred)
+static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct iattr *sattr)
 {
-       struct nfs4_exception exception = { };
-       struct nfs4_state *res = ERR_PTR(-EIO);
-       int err;
+       if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_ACCESS) &&
+           !(sattr->ia_valid & ATTR_ATIME_SET))
+               sattr->ia_valid |= ATTR_ATIME;
 
-       do {
-               err = _nfs4_open_delegated(inode, flags, cred, &res);
-               if (err == 0)
-                       break;
-               res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(inode),
-                                       err, &exception));
-       } while (exception.retry);
-       return res;
+       if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_MODIFY) &&
+           !(sattr->ia_valid & ATTR_MTIME_SET))
+               sattr->ia_valid |= ATTR_MTIME;
 }
 
 /*
  * Returns a referenced nfs4_state
  */
-static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
 {
        struct nfs4_state_owner  *sp;
        struct nfs4_state     *state = NULL;
        struct nfs_server       *server = NFS_SERVER(dir);
        struct nfs_client *clp = server->nfs_client;
        struct nfs4_opendata *opendata;
-       int                     status;
+       int status;
 
        /* Protect against reboot recovery conflicts */
        status = -ENOMEM;
@@ -973,29 +1066,35 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
        status = nfs4_recover_expired_lease(server);
        if (status != 0)
                goto err_put_state_owner;
+       if (path->dentry->d_inode != NULL)
+               nfs4_return_incompatible_delegation(path->dentry->d_inode, flags & (FMODE_READ|FMODE_WRITE));
        down_read(&clp->cl_sem);
        status = -ENOMEM;
-       opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr);
+       opendata = nfs4_opendata_alloc(path, sp, flags, sattr);
        if (opendata == NULL)
                goto err_release_rwsem;
 
+       if (path->dentry->d_inode != NULL)
+               opendata->state = nfs4_get_open_state(path->dentry->d_inode, sp);
+
        status = _nfs4_proc_open(opendata);
        if (status != 0)
-               goto err_opendata_free;
+               goto err_opendata_put;
+
+       if (opendata->o_arg.open_flags & O_EXCL)
+               nfs4_exclusive_attrset(opendata, sattr);
 
-       status = -ENOMEM;
        state = nfs4_opendata_to_nfs4_state(opendata);
-       if (state == NULL)
-               goto err_opendata_free;
-       if (opendata->o_res.delegation_type != 0)
-               nfs_inode_set_delegation(state->inode, cred, &opendata->o_res);
-       nfs4_opendata_free(opendata);
+       status = PTR_ERR(state);
+       if (IS_ERR(state))
+               goto err_opendata_put;
+       nfs4_opendata_put(opendata);
        nfs4_put_state_owner(sp);
        up_read(&clp->cl_sem);
        *res = state;
        return 0;
-err_opendata_free:
-       nfs4_opendata_free(opendata);
+err_opendata_put:
+       nfs4_opendata_put(opendata);
 err_release_rwsem:
        up_read(&clp->cl_sem);
 err_put_state_owner:
@@ -1006,14 +1105,14 @@ out_err:
 }
 
 
-static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred)
 {
        struct nfs4_exception exception = { };
        struct nfs4_state *res;
        int status;
 
        do {
-               status = _nfs4_do_open(dir, dentry, flags, sattr, cred, &res);
+               status = _nfs4_do_open(dir, path, flags, sattr, cred, &res);
                if (status == 0)
                        break;
                /* NOTE: BAD_SEQID means the server and client disagree about the
@@ -1028,7 +1127,9 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry,
                 * the user though...
                 */
                if (status == -NFS4ERR_BAD_SEQID) {
-                       printk(KERN_WARNING "NFS: v4 server returned a bad sequence-id error!\n");
+                       printk(KERN_WARNING "NFS: v4 server %s "
+                                       " returned a bad sequence-id error!\n",
+                                       NFS_SERVER(dir)->nfs_client->cl_hostname);
                        exception.retry = 1;
                        continue;
                }
@@ -1042,6 +1143,11 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry,
                        exception.retry = 1;
                        continue;
                }
+               if (status == -EAGAIN) {
+                       /* We must have found a delegation */
+                       exception.retry = 1;
+                       continue;
+               }
                res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),
                                        status, &exception));
        } while (exception.retry);
@@ -1101,6 +1207,7 @@ static int nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
 }
 
 struct nfs4_closedata {
+       struct path path;
        struct inode *inode;
        struct nfs4_state *state;
        struct nfs_closeargs arg;
@@ -1117,6 +1224,8 @@ static void nfs4_free_closedata(void *data)
        nfs4_put_open_state(calldata->state);
        nfs_free_seqid(calldata->arg.seqid);
        nfs4_put_state_owner(sp);
+       dput(calldata->path.dentry);
+       mntput(calldata->path.mnt);
        kfree(calldata);
 }
 
@@ -1134,8 +1243,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
        nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid);
        switch (task->tk_status) {
                case 0:
-                       memcpy(&state->stateid, &calldata->res.stateid,
-                                       sizeof(state->stateid));
+                       nfs_set_open_stateid(state, &calldata->res.stateid, calldata->arg.open_flags);
                        renew_lease(server, calldata->timestamp);
                        break;
                case -NFS4ERR_STALE_STATEID:
@@ -1160,26 +1268,30 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
                .rpc_resp = &calldata->res,
                .rpc_cred = state->owner->so_cred,
        };
-       int mode = 0, old_mode;
+       int clear_rd, clear_wr, clear_rdwr;
+       int mode;
 
        if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
                return;
-       /* Recalculate the new open mode in case someone reopened the file
-        * while we were waiting in line to be scheduled.
-        */
+
+       mode = FMODE_READ|FMODE_WRITE;
+       clear_rd = clear_wr = clear_rdwr = 0;
        spin_lock(&state->owner->so_lock);
-       spin_lock(&calldata->inode->i_lock);
-       mode = old_mode = state->state;
+       /* Calculate the change in open mode */
        if (state->n_rdwr == 0) {
-               if (state->n_rdonly == 0)
+               if (state->n_rdonly == 0) {
                        mode &= ~FMODE_READ;
-               if (state->n_wronly == 0)
+                       clear_rd |= test_and_clear_bit(NFS_O_RDONLY_STATE, &state->flags);
+                       clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
+               }
+               if (state->n_wronly == 0) {
                        mode &= ~FMODE_WRITE;
+                       clear_wr |= test_and_clear_bit(NFS_O_WRONLY_STATE, &state->flags);
+                       clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
+               }
        }
-       nfs4_state_set_mode_locked(state, mode);
-       spin_unlock(&calldata->inode->i_lock);
        spin_unlock(&state->owner->so_lock);
-       if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) {
+       if (!clear_rd && !clear_wr && !clear_rdwr) {
                /* Note: exit _without_ calling nfs4_close_done */
                task->tk_action = NULL;
                return;
@@ -1209,19 +1321,21 @@ static const struct rpc_call_ops nfs4_close_ops = {
  *
  * NOTE: Caller must be holding the sp->so_owner semaphore!
  */
-int nfs4_do_close(struct inode *inode, struct nfs4_state *state) 
+int nfs4_do_close(struct path *path, struct nfs4_state *state)
 {
-       struct nfs_server *server = NFS_SERVER(inode);
+       struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs4_closedata *calldata;
+       struct nfs4_state_owner *sp = state->owner;
+       struct rpc_task *task;
        int status = -ENOMEM;
 
        calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
        if (calldata == NULL)
                goto out;
-       calldata->inode = inode;
+       calldata->inode = state->inode;
        calldata->state = state;
-       calldata->arg.fh = NFS_FH(inode);
-       calldata->arg.stateid = &state->stateid;
+       calldata->arg.fh = NFS_FH(state->inode);
+       calldata->arg.stateid = &state->open_stateid;
        /* Serialization for the sequence id */
        calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
        if (calldata->arg.seqid == NULL)
@@ -1229,36 +1343,55 @@ int nfs4_do_close(struct inode *inode, struct nfs4_state *state)
        calldata->arg.bitmask = server->attr_bitmask;
        calldata->res.fattr = &calldata->fattr;
        calldata->res.server = server;
+       calldata->path.mnt = mntget(path->mnt);
+       calldata->path.dentry = dget(path->dentry);
 
-       status = nfs4_call_async(server->client, &nfs4_close_ops, calldata);
-       if (status == 0)
-               goto out;
-
-       nfs_free_seqid(calldata->arg.seqid);
+       task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       rpc_put_task(task);
+       return 0;
 out_free_calldata:
        kfree(calldata);
 out:
+       nfs4_put_open_state(state);
+       nfs4_put_state_owner(sp);
        return status;
 }
 
-static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
+static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state)
 {
        struct file *filp;
+       int ret;
 
-       filp = lookup_instantiate_filp(nd, dentry, NULL);
+       /* If the open_intent is for execute, we have an extra check to make */
+       if (nd->intent.open.flags & FMODE_EXEC) {
+               ret = _nfs4_do_access(state->inode,
+                               state->owner->so_cred,
+                               nd->intent.open.flags);
+               if (ret < 0)
+                       goto out_close;
+       }
+       filp = lookup_instantiate_filp(nd, path->dentry, NULL);
        if (!IS_ERR(filp)) {
                struct nfs_open_context *ctx;
                ctx = (struct nfs_open_context *)filp->private_data;
                ctx->state = state;
                return 0;
        }
-       nfs4_close_state(state, nd->intent.open.flags);
-       return PTR_ERR(filp);
+       ret = PTR_ERR(filp);
+out_close:
+       nfs4_close_state(path, state, nd->intent.open.flags);
+       return ret;
 }
 
 struct dentry *
 nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+       struct path path = {
+               .mnt = nd->mnt,
+               .dentry = dentry,
+       };
        struct iattr attr;
        struct rpc_cred *cred;
        struct nfs4_state *state;
@@ -1277,7 +1410,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
        cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
        if (IS_ERR(cred))
                return (struct dentry *)cred;
-       state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
+       state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred);
        put_rpccred(cred);
        if (IS_ERR(state)) {
                if (PTR_ERR(state) == -ENOENT)
@@ -1287,22 +1420,24 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
        res = d_add_unique(dentry, igrab(state->inode));
        if (res != NULL)
                dentry = res;
-       nfs4_intent_set_file(nd, dentry, state);
+       nfs4_intent_set_file(nd, &path, state);
        return res;
 }
 
 int
 nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
 {
+       struct path path = {
+               .mnt = nd->mnt,
+               .dentry = dentry,
+       };
        struct rpc_cred *cred;
        struct nfs4_state *state;
 
        cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
        if (IS_ERR(cred))
                return PTR_ERR(cred);
-       state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
-       if (IS_ERR(state))
-               state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
+       state = nfs4_do_open(dir, &path, openflags, NULL, cred);
        put_rpccred(cred);
        if (IS_ERR(state)) {
                switch (PTR_ERR(state)) {
@@ -1318,10 +1453,10 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
                }
        }
        if (state->inode == dentry->d_inode) {
-               nfs4_intent_set_file(nd, dentry, state);
+               nfs4_intent_set_file(nd, &path, state);
                return 1;
        }
-       nfs4_close_state(state, openflags);
+       nfs4_close_state(&path, state, openflags);
 out_drop:
        d_drop(dentry);
        return 0;
@@ -1559,8 +1694,6 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
        dprintk("NFS call  lookupfh %s\n", name->name);
        status = rpc_call_sync(server->client, &msg, 0);
        dprintk("NFS reply lookupfh: %d\n", status);
-       if (status == -NFS4ERR_MOVED)
-               status = -EREMOTE;
        return status;
 }
 
@@ -1571,10 +1704,13 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
        struct nfs4_exception exception = { };
        int err;
        do {
-               err = nfs4_handle_exception(server,
-                               _nfs4_proc_lookupfh(server, dirfh, name,
-                                                   fhandle, fattr),
-                               &exception);
+               err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr);
+               /* FIXME: !!!! */
+               if (err == -NFS4ERR_MOVED) {
+                       err = -EREMOTE;
+                       break;
+               }
+               err = nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
        return err;
 }
@@ -1582,28 +1718,10 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
 static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name,
                struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
-       int                    status;
-       struct nfs_server *server = NFS_SERVER(dir);
-       struct nfs4_lookup_arg args = {
-               .bitmask = server->attr_bitmask,
-               .dir_fh = NFS_FH(dir),
-               .name = name,
-       };
-       struct nfs4_lookup_res res = {
-               .server = server,
-               .fattr = fattr,
-               .fh = fhandle,
-       };
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
-               .rpc_argp = &args,
-               .rpc_resp = &res,
-       };
-       
-       nfs_fattr_init(fattr);
+       int status;
        
        dprintk("NFS call  lookup %s\n", name->name);
-       status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+       status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr);
        if (status == -NFS4ERR_MOVED)
                status = nfs4_get_referral(dir, name, fattr, fhandle);
        dprintk("NFS reply lookup: %d\n", status);
@@ -1752,6 +1870,10 @@ static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                  int flags, struct nameidata *nd)
 {
+       struct path path = {
+               .mnt = nd->mnt,
+               .dentry = dentry,
+       };
        struct nfs4_state *state;
        struct rpc_cred *cred;
        int status = 0;
@@ -1761,7 +1883,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                status = PTR_ERR(cred);
                goto out;
        }
-       state = nfs4_do_open(dir, dentry, flags, sattr, cred);
+       state = nfs4_do_open(dir, &path, flags, sattr, cred);
        put_rpccred(cred);
        if (IS_ERR(state)) {
                status = PTR_ERR(state);
@@ -1773,11 +1895,12 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
                if (status == 0)
                        nfs_setattr_update_inode(state->inode, sattr);
+               nfs_post_op_update_inode(state->inode, &fattr);
        }
-       if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
-               status = nfs4_intent_set_file(nd, dentry, state);
+       if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
+               status = nfs4_intent_set_file(nd, &path, state);
        else
-               nfs4_close_state(state, flags);
+               nfs4_close_state(&path, state, flags);
 out:
        return status;
 }
@@ -3008,7 +3131,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
        if (status != 0)
                goto out;
        lsp = request->fl_u.nfs4_fl.owner;
-       arg.lock_owner.id = lsp->ls_id
+       arg.lock_owner.id = lsp->ls_id.id;
        status = rpc_call_sync(server->client, &msg, 0);
        switch (status) {
                case 0:
@@ -3152,6 +3275,11 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
 {
        struct nfs4_unlockdata *data;
 
+       /* Ensure this is an unlock - when canceling a lock, the
+        * canceled lock is passed in, and it won't be an unlock.
+        */
+       fl->fl_type = F_UNLCK;
+
        data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid);
        if (data == NULL) {
                nfs_free_seqid(seqid);
@@ -3222,7 +3350,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
                goto out_free;
        p->arg.lock_stateid = &lsp->ls_stateid;
        p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
-       p->arg.lock_owner.id = lsp->ls_id;
+       p->arg.lock_owner.id = lsp->ls_id.id;
        p->lsp = lsp;
        atomic_inc(&lsp->ls_count);
        p->ctx = get_nfs_open_context(ctx);
@@ -3285,7 +3413,7 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
                memcpy(data->lsp->ls_stateid.data, data->res.stateid.data,
                                        sizeof(data->lsp->ls_stateid.data));
                data->lsp->ls_flags |= NFS_LOCK_INITIALIZED;
-               renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp);
+               renew_lease(NFS_SERVER(data->ctx->path.dentry->d_inode), data->timestamp);
        }
        nfs_increment_lock_seqid(data->rpc_status, data->arg.lock_seqid);
 out:
index 8ed79d5c54f9449a4122bb77f4dffcd796a6ec09..e9662ba81d86be1cff5ebef64ffeb7117814936a 100644 (file)
  * subsequent patch.
  */
 
+#include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_idmap.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
+#include <linux/random.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
 
@@ -69,33 +71,14 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
        return status;
 }
 
-u32
-nfs4_alloc_lockowner_id(struct nfs_client *clp)
-{
-       return clp->cl_lockowner_id ++;
-}
-
-static struct nfs4_state_owner *
-nfs4_client_grab_unused(struct nfs_client *clp, struct rpc_cred *cred)
-{
-       struct nfs4_state_owner *sp = NULL;
-
-       if (!list_empty(&clp->cl_unused)) {
-               sp = list_entry(clp->cl_unused.next, struct nfs4_state_owner, so_list);
-               atomic_inc(&sp->so_count);
-               sp->so_cred = cred;
-               list_move(&sp->so_list, &clp->cl_state_owners);
-               clp->cl_nunused--;
-       }
-       return sp;
-}
-
 struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
 {
        struct nfs4_state_owner *sp;
+       struct rb_node *pos;
        struct rpc_cred *cred = NULL;
 
-       list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+       for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
+               sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
                if (list_empty(&sp->so_states))
                        continue;
                cred = get_rpccred(sp->so_cred);
@@ -107,32 +90,146 @@ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
 static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
 {
        struct nfs4_state_owner *sp;
+       struct rb_node *pos;
 
-       if (!list_empty(&clp->cl_state_owners)) {
-               sp = list_entry(clp->cl_state_owners.next,
-                               struct nfs4_state_owner, so_list);
+       pos = rb_first(&clp->cl_state_owners);
+       if (pos != NULL) {
+               sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
                return get_rpccred(sp->so_cred);
        }
        return NULL;
 }
 
+static void nfs_alloc_unique_id(struct rb_root *root, struct nfs_unique_id *new,
+               __u64 minval, int maxbits)
+{
+       struct rb_node **p, *parent;
+       struct nfs_unique_id *pos;
+       __u64 mask = ~0ULL;
+
+       if (maxbits < 64)
+               mask = (1ULL << maxbits) - 1ULL;
+
+       /* Ensure distribution is more or less flat */
+       get_random_bytes(&new->id, sizeof(new->id));
+       new->id &= mask;
+       if (new->id < minval)
+               new->id += minval;
+retry:
+       p = &root->rb_node;
+       parent = NULL;
+
+       while (*p != NULL) {
+               parent = *p;
+               pos = rb_entry(parent, struct nfs_unique_id, rb_node);
+
+               if (new->id < pos->id)
+                       p = &(*p)->rb_left;
+               else if (new->id > pos->id)
+                       p = &(*p)->rb_right;
+               else
+                       goto id_exists;
+       }
+       rb_link_node(&new->rb_node, parent, p);
+       rb_insert_color(&new->rb_node, root);
+       return;
+id_exists:
+       for (;;) {
+               new->id++;
+               if (new->id < minval || (new->id & mask) != new->id) {
+                       new->id = minval;
+                       break;
+               }
+               parent = rb_next(parent);
+               if (parent == NULL)
+                       break;
+               pos = rb_entry(parent, struct nfs_unique_id, rb_node);
+               if (new->id < pos->id)
+                       break;
+       }
+       goto retry;
+}
+
+static void nfs_free_unique_id(struct rb_root *root, struct nfs_unique_id *id)
+{
+       rb_erase(&id->rb_node, root);
+}
+
 static struct nfs4_state_owner *
-nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred)
+nfs4_find_state_owner(struct nfs_server *server, struct rpc_cred *cred)
 {
+       struct nfs_client *clp = server->nfs_client;
+       struct rb_node **p = &clp->cl_state_owners.rb_node,
+                      *parent = NULL;
        struct nfs4_state_owner *sp, *res = NULL;
 
-       list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
-               if (sp->so_cred != cred)
+       while (*p != NULL) {
+               parent = *p;
+               sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
+
+               if (server < sp->so_server) {
+                       p = &parent->rb_left;
                        continue;
-               atomic_inc(&sp->so_count);
-               /* Move to the head of the list */
-               list_move(&sp->so_list, &clp->cl_state_owners);
-               res = sp;
-               break;
+               }
+               if (server > sp->so_server) {
+                       p = &parent->rb_right;
+                       continue;
+               }
+               if (cred < sp->so_cred)
+                       p = &parent->rb_left;
+               else if (cred > sp->so_cred)
+                       p = &parent->rb_right;
+               else {
+                       atomic_inc(&sp->so_count);
+                       res = sp;
+                       break;
+               }
        }
        return res;
 }
 
+static struct nfs4_state_owner *
+nfs4_insert_state_owner(struct nfs_client *clp, struct nfs4_state_owner *new)
+{
+       struct rb_node **p = &clp->cl_state_owners.rb_node,
+                      *parent = NULL;
+       struct nfs4_state_owner *sp;
+
+       while (*p != NULL) {
+               parent = *p;
+               sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
+
+               if (new->so_server < sp->so_server) {
+                       p = &parent->rb_left;
+                       continue;
+               }
+               if (new->so_server > sp->so_server) {
+                       p = &parent->rb_right;
+                       continue;
+               }
+               if (new->so_cred < sp->so_cred)
+                       p = &parent->rb_left;
+               else if (new->so_cred > sp->so_cred)
+                       p = &parent->rb_right;
+               else {
+                       atomic_inc(&sp->so_count);
+                       return sp;
+               }
+       }
+       nfs_alloc_unique_id(&clp->cl_openowner_id, &new->so_owner_id, 1, 64);
+       rb_link_node(&new->so_client_node, parent, p);
+       rb_insert_color(&new->so_client_node, &clp->cl_state_owners);
+       return new;
+}
+
+static void
+nfs4_remove_state_owner(struct nfs_client *clp, struct nfs4_state_owner *sp)
+{
+       if (!RB_EMPTY_NODE(&sp->so_client_node))
+               rb_erase(&sp->so_client_node, &clp->cl_state_owners);
+       nfs_free_unique_id(&clp->cl_openowner_id, &sp->so_owner_id);
+}
+
 /*
  * nfs4_alloc_state_owner(): this is called on the OPEN or CREATE path to
  * create a new state_owner.
@@ -160,10 +257,14 @@ nfs4_alloc_state_owner(void)
 void
 nfs4_drop_state_owner(struct nfs4_state_owner *sp)
 {
-       struct nfs_client *clp = sp->so_client;
-       spin_lock(&clp->cl_lock);
-       list_del_init(&sp->so_list);
-       spin_unlock(&clp->cl_lock);
+       if (!RB_EMPTY_NODE(&sp->so_client_node)) {
+               struct nfs_client *clp = sp->so_client;
+
+               spin_lock(&clp->cl_lock);
+               rb_erase(&sp->so_client_node, &clp->cl_state_owners);
+               RB_CLEAR_NODE(&sp->so_client_node);
+               spin_unlock(&clp->cl_lock);
+       }
 }
 
 /*
@@ -175,26 +276,25 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
        struct nfs_client *clp = server->nfs_client;
        struct nfs4_state_owner *sp, *new;
 
-       get_rpccred(cred);
-       new = nfs4_alloc_state_owner();
        spin_lock(&clp->cl_lock);
-       sp = nfs4_find_state_owner(clp, cred);
-       if (sp == NULL)
-               sp = nfs4_client_grab_unused(clp, cred);
-       if (sp == NULL && new != NULL) {
-               list_add(&new->so_list, &clp->cl_state_owners);
-               new->so_client = clp;
-               new->so_id = nfs4_alloc_lockowner_id(clp);
-               new->so_cred = cred;
-               sp = new;
-               new = NULL;
-       }
+       sp = nfs4_find_state_owner(server, cred);
        spin_unlock(&clp->cl_lock);
-       kfree(new);
        if (sp != NULL)
                return sp;
-       put_rpccred(cred);
-       return NULL;
+       new = nfs4_alloc_state_owner();
+       if (new == NULL)
+               return NULL;
+       new->so_client = clp;
+       new->so_server = server;
+       new->so_cred = cred;
+       spin_lock(&clp->cl_lock);
+       sp = nfs4_insert_state_owner(clp, new);
+       spin_unlock(&clp->cl_lock);
+       if (sp == new)
+               get_rpccred(cred);
+       else
+               kfree(new);
+       return sp;
 }
 
 /*
@@ -208,18 +308,7 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
 
        if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock))
                return;
-       if (clp->cl_nunused >= OPENOWNER_POOL_SIZE)
-               goto out_free;
-       if (list_empty(&sp->so_list))
-               goto out_free;
-       list_move(&sp->so_list, &clp->cl_unused);
-       clp->cl_nunused++;
-       spin_unlock(&clp->cl_lock);
-       put_rpccred(cred);
-       cred = NULL;
-       return;
-out_free:
-       list_del(&sp->so_list);
+       nfs4_remove_state_owner(clp, sp);
        spin_unlock(&clp->cl_lock);
        put_rpccred(cred);
        kfree(sp);
@@ -236,6 +325,7 @@ nfs4_alloc_open_state(void)
        atomic_set(&state->count, 1);
        INIT_LIST_HEAD(&state->lock_states);
        spin_lock_init(&state->state_lock);
+       seqlock_init(&state->seqlock);
        return state;
 }
 
@@ -263,13 +353,10 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
        struct nfs4_state *state;
 
        list_for_each_entry(state, &nfsi->open_states, inode_states) {
-               /* Is this in the process of being freed? */
-               if (state->state == 0)
+               if (state->owner != owner)
                        continue;
-               if (state->owner == owner) {
-                       atomic_inc(&state->count);
+               if (atomic_inc_not_zero(&state->count))
                        return state;
-               }
        }
        return NULL;
 }
@@ -341,16 +428,15 @@ void nfs4_put_open_state(struct nfs4_state *state)
 /*
  * Close the current file.
  */
-void nfs4_close_state(struct nfs4_state *state, mode_t mode)
+void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
 {
-       struct inode *inode = state->inode;
        struct nfs4_state_owner *owner = state->owner;
-       int oldstate, newstate = 0;
+       int call_close = 0;
+       int newstate;
 
        atomic_inc(&owner->so_count);
        /* Protect against nfs4_find_state() */
        spin_lock(&owner->so_lock);
-       spin_lock(&inode->i_lock);
        switch (mode & (FMODE_READ | FMODE_WRITE)) {
                case FMODE_READ:
                        state->n_rdonly--;
@@ -361,24 +447,29 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
                case FMODE_READ|FMODE_WRITE:
                        state->n_rdwr--;
        }
-       oldstate = newstate = state->state;
+       newstate = FMODE_READ|FMODE_WRITE;
        if (state->n_rdwr == 0) {
-               if (state->n_rdonly == 0)
+               if (state->n_rdonly == 0) {
                        newstate &= ~FMODE_READ;
-               if (state->n_wronly == 0)
+                       call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags);
+                       call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
+               }
+               if (state->n_wronly == 0) {
                        newstate &= ~FMODE_WRITE;
+                       call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags);
+                       call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
+               }
+               if (newstate == 0)
+                       clear_bit(NFS_DELEGATED_STATE, &state->flags);
        }
-       if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
-               nfs4_state_set_mode_locked(state, newstate);
-               oldstate = newstate;
-       }
-       spin_unlock(&inode->i_lock);
+       nfs4_state_set_mode_locked(state, newstate);
        spin_unlock(&owner->so_lock);
 
-       if (oldstate != newstate && nfs4_do_close(inode, state) == 0)
-               return;
-       nfs4_put_open_state(state);
-       nfs4_put_state_owner(owner);
+       if (!call_close) {
+               nfs4_put_open_state(state);
+               nfs4_put_state_owner(owner);
+       } else
+               nfs4_do_close(path, state);
 }
 
 /*
@@ -415,12 +506,22 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
        atomic_set(&lsp->ls_count, 1);
        lsp->ls_owner = fl_owner;
        spin_lock(&clp->cl_lock);
-       lsp->ls_id = nfs4_alloc_lockowner_id(clp);
+       nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64);
        spin_unlock(&clp->cl_lock);
        INIT_LIST_HEAD(&lsp->ls_locks);
        return lsp;
 }
 
+static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
+{
+       struct nfs_client *clp = lsp->ls_state->owner->so_client;
+
+       spin_lock(&clp->cl_lock);
+       nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id);
+       spin_unlock(&clp->cl_lock);
+       kfree(lsp);
+}
+
 /*
  * Return a compatible lock_state. If no initialized lock_state structure
  * exists, return an uninitialized one.
@@ -450,7 +551,8 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
                        return NULL;
        }
        spin_unlock(&state->state_lock);
-       kfree(new);
+       if (new != NULL)
+               nfs4_free_lock_state(new);
        return lsp;
 }
 
@@ -471,7 +573,7 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
        if (list_empty(&state->lock_states))
                clear_bit(LK_STATE_IN_USE, &state->flags);
        spin_unlock(&state->state_lock);
-       kfree(lsp);
+       nfs4_free_lock_state(lsp);
 }
 
 static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
@@ -513,8 +615,12 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
 void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
 {
        struct nfs4_lock_state *lsp;
+       int seq;
 
-       memcpy(dst, &state->stateid, sizeof(*dst));
+       do {
+               seq = read_seqbegin(&state->seqlock);
+               memcpy(dst, &state->stateid, sizeof(*dst));
+       } while (read_seqretry(&state->seqlock, seq));
        if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
                return;
 
@@ -557,12 +663,18 @@ void nfs_free_seqid(struct nfs_seqid *seqid)
  * failed with a seqid incrementing error -
  * see comments nfs_fs.h:seqid_mutating_error()
  */
-static inline void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
+static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
 {
        switch (status) {
                case 0:
                        break;
                case -NFS4ERR_BAD_SEQID:
+                       if (seqid->sequence->flags & NFS_SEQID_CONFIRMED)
+                               return;
+                       printk(KERN_WARNING "NFS: v4 server returned a bad"
+                                       "sequence-id error on an"
+                                       "unconfirmed sequence %p!\n",
+                                       seqid->sequence);
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_STALE_STATEID:
                case -NFS4ERR_BAD_STATEID:
@@ -586,7 +698,7 @@ void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
                                struct nfs4_state_owner, so_seqid);
                nfs4_drop_state_owner(sp);
        }
-       return nfs_increment_seqid(status, seqid);
+       nfs_increment_seqid(status, seqid);
 }
 
 /*
@@ -596,7 +708,7 @@ void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
  */
 void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid)
 {
-       return nfs_increment_seqid(status, seqid);
+       nfs_increment_seqid(status, seqid);
 }
 
 int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
@@ -748,15 +860,21 @@ out_err:
 static void nfs4_state_mark_reclaim(struct nfs_client *clp)
 {
        struct nfs4_state_owner *sp;
+       struct rb_node *pos;
        struct nfs4_state *state;
        struct nfs4_lock_state *lock;
 
        /* Reset all sequence ids to zero */
-       list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+       for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
+               sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
                sp->so_seqid.counter = 0;
                sp->so_seqid.flags = 0;
                spin_lock(&sp->so_lock);
                list_for_each_entry(state, &sp->so_states, open_states) {
+                       clear_bit(NFS_DELEGATED_STATE, &state->flags);
+                       clear_bit(NFS_O_RDONLY_STATE, &state->flags);
+                       clear_bit(NFS_O_WRONLY_STATE, &state->flags);
+                       clear_bit(NFS_O_RDWR_STATE, &state->flags);
                        list_for_each_entry(lock, &state->lock_states, ls_locks) {
                                lock->ls_seqid.counter = 0;
                                lock->ls_seqid.flags = 0;
@@ -771,6 +889,7 @@ static int reclaimer(void *ptr)
 {
        struct nfs_client *clp = ptr;
        struct nfs4_state_owner *sp;
+       struct rb_node *pos;
        struct nfs4_state_recovery_ops *ops;
        struct rpc_cred *cred;
        int status = 0;
@@ -816,7 +935,8 @@ restart_loop:
        /* Mark all delegations for reclaim */
        nfs_delegation_mark_reclaim(clp);
        /* Note: list is protected by exclusive lock on cl->cl_sem */
-       list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+       for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
+               sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
                status = nfs4_reclaim_open_state(ops, sp);
                if (status < 0) {
                        if (status == -NFS4ERR_NO_GRACE) {
index 8003c91ccb9a0a5ca374f58dee3594b00615c5f0..c08738441f732216f7b785fa3805860475a40917 100644 (file)
@@ -68,9 +68,10 @@ static int nfs4_stat_to_errno(int);
 #endif
 
 /* lock,open owner id: 
- * we currently use size 1 (u32) out of (NFS4_OPAQUE_LIMIT  >> 2)
+ * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT  >> 2)
  */
-#define owner_id_maxsz          (1 + 1)
+#define open_owner_id_maxsz    (1 + 4)
+#define lock_owner_id_maxsz    (1 + 4)
 #define compound_encode_hdr_maxsz      (3 + (NFS4_MAXTAGLEN >> 2))
 #define compound_decode_hdr_maxsz      (3 + (NFS4_MAXTAGLEN >> 2))
 #define op_encode_hdr_maxsz    (1)
@@ -87,9 +88,11 @@ static int nfs4_stat_to_errno(int);
 #define encode_getattr_maxsz    (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
 #define nfs4_name_maxsz                (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
 #define nfs4_path_maxsz                (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
+#define nfs4_owner_maxsz       (1 + XDR_QUADLEN(IDMAP_NAMESZ))
+#define nfs4_group_maxsz       (1 + XDR_QUADLEN(IDMAP_NAMESZ))
 /* This is based on getfattr, which uses the most attributes: */
 #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
-                               3 + 3 + 3 + 2 * nfs4_name_maxsz))
+                               3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz))
 #define nfs4_fattr_maxsz       (nfs4_fattr_bitmap_maxsz + \
                                nfs4_fattr_value_maxsz)
 #define decode_getattr_maxsz    (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
@@ -116,8 +119,27 @@ static int nfs4_stat_to_errno(int);
                                3 + (NFS4_VERIFIER_SIZE >> 2))
 #define decode_setclientid_confirm_maxsz \
                                (op_decode_hdr_maxsz)
-#define encode_lookup_maxsz    (op_encode_hdr_maxsz + \
-                               1 + ((3 + NFS4_FHSIZE) >> 2))
+#define encode_lookup_maxsz    (op_encode_hdr_maxsz + nfs4_name_maxsz)
+#define decode_lookup_maxsz    (op_decode_hdr_maxsz)
+#define encode_share_access_maxsz \
+                               (2)
+#define encode_createmode_maxsz        (1 + nfs4_fattr_maxsz)
+#define encode_opentype_maxsz  (1 + encode_createmode_maxsz)
+#define encode_claim_null_maxsz        (1 + nfs4_name_maxsz)
+#define encode_open_maxsz      (op_encode_hdr_maxsz + \
+                               2 + encode_share_access_maxsz + 2 + \
+                               open_owner_id_maxsz + \
+                               encode_opentype_maxsz + \
+                               encode_claim_null_maxsz)
+#define decode_ace_maxsz       (3 + nfs4_owner_maxsz)
+#define decode_delegation_maxsz        (1 + XDR_QUADLEN(NFS4_STATEID_SIZE) + 1 + \
+                               decode_ace_maxsz)
+#define decode_change_info_maxsz       (5)
+#define decode_open_maxsz      (op_decode_hdr_maxsz + \
+                               XDR_QUADLEN(NFS4_STATEID_SIZE) + \
+                               decode_change_info_maxsz + 1 + \
+                               nfs4_fattr_bitmap_maxsz + \
+                               decode_delegation_maxsz)
 #define encode_remove_maxsz    (op_encode_hdr_maxsz + \
                                nfs4_name_maxsz)
 #define encode_rename_maxsz    (op_encode_hdr_maxsz + \
@@ -134,9 +156,15 @@ static int nfs4_stat_to_errno(int);
 #define encode_create_maxsz    (op_encode_hdr_maxsz + \
                                2 + nfs4_name_maxsz + \
                                nfs4_fattr_maxsz)
-#define decode_create_maxsz    (op_decode_hdr_maxsz + 8)
+#define decode_create_maxsz    (op_decode_hdr_maxsz + \
+                               decode_change_info_maxsz + \
+                               nfs4_fattr_bitmap_maxsz)
 #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
 #define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
+#define encode_fs_locations_maxsz \
+                               (encode_getattr_maxsz)
+#define decode_fs_locations_maxsz \
+                               (0)
 #define NFS4_enc_compound_sz   (1024)  /* XXX: large enough? */
 #define NFS4_dec_compound_sz   (1024)  /* XXX: large enough? */
 #define NFS4_enc_read_sz       (compound_encode_hdr_maxsz + \
@@ -174,16 +202,21 @@ static int nfs4_stat_to_errno(int);
                                op_decode_hdr_maxsz + 2 + \
                                decode_getattr_maxsz)
 #define NFS4_enc_open_sz        (compound_encode_hdr_maxsz + \
-                                encode_putfh_maxsz + \
-                                op_encode_hdr_maxsz + \
-                                13 + 3 + 2 + 64 + \
-                                encode_getattr_maxsz + \
-                                encode_getfh_maxsz)
+                               encode_putfh_maxsz + \
+                               encode_savefh_maxsz + \
+                               encode_open_maxsz + \
+                               encode_getfh_maxsz + \
+                               encode_getattr_maxsz + \
+                               encode_restorefh_maxsz + \
+                               encode_getattr_maxsz)
 #define NFS4_dec_open_sz        (compound_decode_hdr_maxsz + \
-                                decode_putfh_maxsz + \
-                                op_decode_hdr_maxsz + 4 + 5 + 2 + 3 + \
-                                decode_getattr_maxsz + \
-                                decode_getfh_maxsz)
+                               decode_putfh_maxsz + \
+                               decode_savefh_maxsz + \
+                               decode_open_maxsz + \
+                               decode_getfh_maxsz + \
+                               decode_getattr_maxsz + \
+                               decode_restorefh_maxsz + \
+                               decode_getattr_maxsz)
 #define NFS4_enc_open_confirm_sz      \
                                 (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
@@ -193,12 +226,12 @@ static int nfs4_stat_to_errno(int);
                                         op_decode_hdr_maxsz + 4)
 #define NFS4_enc_open_noattr_sz        (compound_encode_hdr_maxsz + \
                                        encode_putfh_maxsz + \
-                                       op_encode_hdr_maxsz + \
-                                       11)
+                                       encode_open_maxsz + \
+                                       encode_getattr_maxsz)
 #define NFS4_dec_open_noattr_sz        (compound_decode_hdr_maxsz + \
                                        decode_putfh_maxsz + \
-                                       op_decode_hdr_maxsz + \
-                                       4 + 5 + 2 + 3)
+                                       decode_open_maxsz + \
+                                       decode_getattr_maxsz)
 #define NFS4_enc_open_downgrade_sz \
                                (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
@@ -256,19 +289,19 @@ static int nfs4_stat_to_errno(int);
                                op_encode_hdr_maxsz + \
                                1 + 1 + 2 + 2 + \
                                1 + 4 + 1 + 2 + \
-                               owner_id_maxsz)
+                               lock_owner_id_maxsz)
 #define NFS4_dec_lock_sz        (compound_decode_hdr_maxsz + \
                                decode_putfh_maxsz + \
                                decode_getattr_maxsz + \
                                op_decode_hdr_maxsz + \
                                2 + 2 + 1 + 2 + \
-                               owner_id_maxsz)
+                               lock_owner_id_maxsz)
 #define NFS4_enc_lockt_sz       (compound_encode_hdr_maxsz + \
                                encode_putfh_maxsz + \
                                encode_getattr_maxsz + \
                                op_encode_hdr_maxsz + \
                                1 + 2 + 2 + 2 + \
-                               owner_id_maxsz)
+                               lock_owner_id_maxsz)
 #define NFS4_dec_lockt_sz       (NFS4_dec_lock_sz)
 #define NFS4_enc_locku_sz       (compound_encode_hdr_maxsz + \
                                encode_putfh_maxsz + \
@@ -298,7 +331,7 @@ static int nfs4_stat_to_errno(int);
                                encode_getfh_maxsz)
 #define NFS4_dec_lookup_sz     (compound_decode_hdr_maxsz + \
                                decode_putfh_maxsz + \
-                               op_decode_hdr_maxsz + \
+                               decode_lookup_maxsz + \
                                decode_getattr_maxsz + \
                                decode_getfh_maxsz)
 #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
@@ -417,12 +450,13 @@ static int nfs4_stat_to_errno(int);
 #define NFS4_enc_fs_locations_sz \
                                (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
-                                encode_getattr_maxsz)
+                                encode_lookup_maxsz + \
+                                encode_fs_locations_maxsz)
 #define NFS4_dec_fs_locations_sz \
                                (compound_decode_hdr_maxsz + \
                                 decode_putfh_maxsz + \
-                                op_decode_hdr_maxsz + \
-                                nfs4_fattr_bitmap_maxsz)
+                                decode_lookup_maxsz + \
+                                decode_fs_locations_maxsz)
 
 static struct {
        unsigned int    mode;
@@ -793,13 +827,14 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args)
        WRITE64(nfs4_lock_length(args->fl));
        WRITE32(args->new_lock_owner);
        if (args->new_lock_owner){
-               RESERVE_SPACE(4+NFS4_STATEID_SIZE+20);
+               RESERVE_SPACE(4+NFS4_STATEID_SIZE+32);
                WRITE32(args->open_seqid->sequence->counter);
                WRITEMEM(args->open_stateid->data, NFS4_STATEID_SIZE);
                WRITE32(args->lock_seqid->sequence->counter);
                WRITE64(args->lock_owner.clientid);
-               WRITE32(4);
-               WRITE32(args->lock_owner.id);
+               WRITE32(16);
+               WRITEMEM("lock id:", 8);
+               WRITE64(args->lock_owner.id);
        }
        else {
                RESERVE_SPACE(NFS4_STATEID_SIZE+4);
@@ -814,14 +849,15 @@ static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *arg
 {
        __be32 *p;
 
-       RESERVE_SPACE(40);
+       RESERVE_SPACE(52);
        WRITE32(OP_LOCKT);
        WRITE32(nfs4_lock_type(args->fl, 0));
        WRITE64(args->fl->fl_start);
        WRITE64(nfs4_lock_length(args->fl));
        WRITE64(args->lock_owner.clientid);
-       WRITE32(4);
-       WRITE32(args->lock_owner.id);
+       WRITE32(16);
+       WRITEMEM("lock id:", 8);
+       WRITE64(args->lock_owner.id);
 
        return 0;
 }
@@ -886,10 +922,11 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
        WRITE32(OP_OPEN);
        WRITE32(arg->seqid->sequence->counter);
        encode_share_access(xdr, arg->open_flags);
-       RESERVE_SPACE(16);
+       RESERVE_SPACE(28);
        WRITE64(arg->clientid);
-       WRITE32(4);
-       WRITE32(arg->id);
+       WRITE32(16);
+       WRITEMEM("open id:", 8);
+       WRITE64(arg->id);
 }
 
 static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
@@ -1071,7 +1108,7 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
 
 static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req)
 {
-       struct rpc_auth *auth = req->rq_task->tk_auth;
+       struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
        uint32_t attrs[2] = {
                FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
                FATTR4_WORD1_MOUNTED_ON_FILEID,
@@ -1117,7 +1154,7 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
 
 static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req)
 {
-       struct rpc_auth *auth = req->rq_task->tk_auth;
+       struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
        unsigned int replen;
        __be32 *p;
 
@@ -1735,7 +1772,7 @@ out:
  */
 static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
 {
-       struct rpc_auth *auth = req->rq_task->tk_auth;
+       struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
                .nops = 2,
@@ -1795,7 +1832,7 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
                struct nfs_getaclargs *args)
 {
        struct xdr_stream xdr;
-       struct rpc_auth *auth = req->rq_task->tk_auth;
+       struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
        struct compound_hdr hdr = {
                .nops   = 2,
        };
@@ -2030,7 +2067,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
        struct compound_hdr hdr = {
                .nops = 3,
        };
-       struct rpc_auth *auth = req->rq_task->tk_auth;
+       struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
        int replen;
        int status;
 
@@ -3269,7 +3306,7 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
 static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
 {
         __be32 *p;
-        uint32_t bmlen;
+       uint32_t savewords, bmlen, i;
         int status;
 
         status = decode_op_hdr(xdr, OP_OPEN);
@@ -3287,7 +3324,12 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
                 goto xdr_error;
 
         READ_BUF(bmlen << 2);
-        p += bmlen;
+       savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
+       for (i = 0; i < savewords; ++i)
+               READ32(res->attrset[i]);
+       for (; i < NFS4_BITMAP_SIZE; i++)
+               res->attrset[i] = 0;
+
        return decode_delegation(xdr, res);
 xdr_error:
        dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen);
index 49d1008ce1d702c8307249f4a1e1e94d389e72b0..3490322d11459f0023bc60d56da1bddc0c06b9c5 100644 (file)
@@ -428,7 +428,7 @@ static int __init root_nfs_getport(int program, int version, int proto)
        printk(KERN_NOTICE "Looking up port of RPC %d/%d on %u.%u.%u.%u\n",
                program, version, NIPQUAD(servaddr));
        set_sockaddr(&sin, servaddr, 0);
-       return rpcb_getport_external(&sin, program, version, proto);
+       return rpcb_getport_sync(&sin, program, version, proto);
 }
 
 
@@ -496,7 +496,8 @@ static int __init root_nfs_get_handle(void)
                                        NFS_MNT3_VERSION : NFS_MNT_VERSION;
 
        set_sockaddr(&sin, servaddr, htons(mount_port));
-       status = nfsroot_mount(&sin, nfs_path, &fh, version, protocol);
+       status = nfs_mount((struct sockaddr *) &sin, sizeof(sin), NULL,
+                          nfs_path, version, protocol, &fh);
        if (status < 0)
                printk(KERN_ERR "Root-NFS: Server returned error %d "
                                "while mounting %s\n", status, nfs_path);
index c5bb51a29e8072198c57963f5c3c9dbf86ebc6ab..f56dae5216f4dfadd82bc316a439487c8fd2cc72 100644 (file)
@@ -85,9 +85,8 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
        req->wb_offset  = offset;
        req->wb_pgbase  = offset;
        req->wb_bytes   = count;
-       atomic_set(&req->wb_count, 1);
        req->wb_context = get_nfs_open_context(ctx);
-
+       kref_init(&req->wb_kref);
        return req;
 }
 
@@ -109,30 +108,31 @@ void nfs_unlock_request(struct nfs_page *req)
 }
 
 /**
- * nfs_set_page_writeback_locked - Lock a request for writeback
+ * nfs_set_page_tag_locked - Tag a request as locked
  * @req:
  */
-int nfs_set_page_writeback_locked(struct nfs_page *req)
+static int nfs_set_page_tag_locked(struct nfs_page *req)
 {
-       struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
+       struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode);
 
        if (!nfs_lock_request(req))
                return 0;
-       radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
+       radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
        return 1;
 }
 
 /**
- * nfs_clear_page_writeback - Unlock request and wake up sleepers
+ * nfs_clear_page_tag_locked - Clear request tag and wake up sleepers
  */
-void nfs_clear_page_writeback(struct nfs_page *req)
+void nfs_clear_page_tag_locked(struct nfs_page *req)
 {
-       struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
+       struct inode *inode = req->wb_context->path.dentry->d_inode;
+       struct nfs_inode *nfsi = NFS_I(inode);
 
        if (req->wb_page != NULL) {
-               spin_lock(&nfsi->req_lock);
-               radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
-               spin_unlock(&nfsi->req_lock);
+               spin_lock(&inode->i_lock);
+               radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
+               spin_unlock(&inode->i_lock);
        }
        nfs_unlock_request(req);
 }
@@ -160,11 +160,9 @@ void nfs_clear_request(struct nfs_page *req)
  *
  * Note: Should never be called with the spinlock held!
  */
-void
-nfs_release_request(struct nfs_page *req)
+static void nfs_free_request(struct kref *kref)
 {
-       if (!atomic_dec_and_test(&req->wb_count))
-               return;
+       struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref);
 
        /* Release struct file or cached credential */
        nfs_clear_request(req);
@@ -172,6 +170,11 @@ nfs_release_request(struct nfs_page *req)
        nfs_page_free(req);
 }
 
+void nfs_release_request(struct nfs_page *req)
+{
+       kref_put(&req->wb_kref, nfs_free_request);
+}
+
 static int nfs_wait_bit_interruptible(void *word)
 {
        int ret = 0;
@@ -193,7 +196,7 @@ static int nfs_wait_bit_interruptible(void *word)
 int
 nfs_wait_on_request(struct nfs_page *req)
 {
-        struct rpc_clnt        *clnt = NFS_CLIENT(req->wb_context->dentry->d_inode);
+       struct rpc_clnt *clnt = NFS_CLIENT(req->wb_context->path.dentry->d_inode);
        sigset_t oldmask;
        int ret = 0;
 
@@ -379,20 +382,20 @@ void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index)
 /**
  * nfs_scan_list - Scan a list for matching requests
  * @nfsi: NFS inode
- * @head: One of the NFS inode request lists
  * @dst: Destination list
  * @idx_start: lower bound of page->index to scan
  * @npages: idx_start + npages sets the upper bound to scan.
+ * @tag: tag to scan for
  *
  * Moves elements from one of the inode request lists.
  * If the number of requests is set to 0, the entire address_space
  * starting at index idx_start, is scanned.
  * The requests are *not* checked to ensure that they form a contiguous set.
- * You must be holding the inode's req_lock when calling this function
+ * You must be holding the inode's i_lock when calling this function
  */
-int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
+int nfs_scan_list(struct nfs_inode *nfsi,
                struct list_head *dst, pgoff_t idx_start,
-               unsigned int npages)
+               unsigned int npages, int tag)
 {
        struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
        struct nfs_page *req;
@@ -407,9 +410,9 @@ int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
                idx_end = idx_start + npages - 1;
 
        for (;;) {
-               found = radix_tree_gang_lookup(&nfsi->nfs_page_tree,
+               found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
                                (void **)&pgvec[0], idx_start,
-                               NFS_SCAN_MAXENTRIES);
+                               NFS_SCAN_MAXENTRIES, tag);
                if (found <= 0)
                        break;
                for (i = 0; i < found; i++) {
@@ -417,15 +420,18 @@ int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
                        if (req->wb_index > idx_end)
                                goto out;
                        idx_start = req->wb_index + 1;
-                       if (req->wb_list_head != head)
-                               continue;
-                       if (nfs_set_page_writeback_locked(req)) {
+                       if (nfs_set_page_tag_locked(req)) {
                                nfs_list_remove_request(req);
+                               radix_tree_tag_clear(&nfsi->nfs_page_tree,
+                                               req->wb_index, tag);
                                nfs_list_add_request(req, dst);
                                res++;
+                               if (res == INT_MAX)
+                                       goto out;
                        }
                }
-
+               /* for latency reduction */
+               cond_resched_lock(&nfsi->vfs_inode.i_lock);
        }
 out:
        return res;
index 7bd7cb95c034d8bbcdbcdb05fbba5f46a291e68c..6ae2e58ed05af3620888a412e2abcee8a5c8bd9d 100644 (file)
@@ -145,8 +145,8 @@ static void nfs_readpage_release(struct nfs_page *req)
        unlock_page(req->wb_page);
 
        dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
-                       req->wb_context->dentry->d_inode->i_sb->s_id,
-                       (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+                       req->wb_context->path.dentry->d_inode->i_sb->s_id,
+                       (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
                        req->wb_bytes,
                        (long long)req_offset(req));
        nfs_clear_request(req);
@@ -164,7 +164,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
        int flags;
 
        data->req         = req;
-       data->inode       = inode = req->wb_context->dentry->d_inode;
+       data->inode       = inode = req->wb_context->path.dentry->d_inode;
        data->cred        = req->wb_context->cred;
 
        data->args.fh     = NFS_FH(inode);
@@ -483,17 +483,19 @@ int nfs_readpage(struct file *file, struct page *page)
         */
        error = nfs_wb_page(inode, page);
        if (error)
-               goto out_error;
+               goto out_unlock;
+       if (PageUptodate(page))
+               goto out_unlock;
 
        error = -ESTALE;
        if (NFS_STALE(inode))
-               goto out_error;
+               goto out_unlock;
 
        if (file == NULL) {
                error = -EBADF;
                ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
                if (ctx == NULL)
-                       goto out_error;
+                       goto out_unlock;
        } else
                ctx = get_nfs_open_context((struct nfs_open_context *)
                                file->private_data);
@@ -502,8 +504,7 @@ int nfs_readpage(struct file *file, struct page *page)
 
        put_nfs_open_context(ctx);
        return error;
-
-out_error:
+out_unlock:
        unlock_page(page);
        return error;
 }
@@ -520,21 +521,32 @@ readpage_async_filler(void *data, struct page *page)
        struct inode *inode = page->mapping->host;
        struct nfs_page *new;
        unsigned int len;
+       int error;
+
+       error = nfs_wb_page(inode, page);
+       if (error)
+               goto out_unlock;
+       if (PageUptodate(page))
+               goto out_unlock;
 
-       nfs_wb_page(inode, page);
        len = nfs_page_length(page);
        if (len == 0)
                return nfs_return_empty_page(page);
+
        new = nfs_create_request(desc->ctx, inode, page, 0, len);
-       if (IS_ERR(new)) {
-                       SetPageError(page);
-                       unlock_page(page);
-                       return PTR_ERR(new);
-       }
+       if (IS_ERR(new))
+               goto out_error;
+
        if (len < PAGE_CACHE_SIZE)
                zero_user_page(page, len, PAGE_CACHE_SIZE - len, KM_USER0);
        nfs_pageio_add_request(desc->pgio, new);
        return 0;
+out_error:
+       error = PTR_ERR(new);
+       SetPageError(page);
+out_unlock:
+       unlock_page(page);
+       return error;
 }
 
 int nfs_readpages(struct file *filp, struct address_space *mapping,
index ca20d3cc260908b485f7d3bf4279ad3d718d97c4..a2b1af89ca1af331763a35f3b90f83864edd66d7 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/inet.h>
 #include <linux/nfs_xdr.h>
 #include <linux/magic.h>
+#include <linux/parser.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
 
+
+struct nfs_parsed_mount_data {
+       int                     flags;
+       int                     rsize, wsize;
+       int                     timeo, retrans;
+       int                     acregmin, acregmax,
+                               acdirmin, acdirmax;
+       int                     namlen;
+       unsigned int            bsize;
+       unsigned int            auth_flavor_len;
+       rpc_authflavor_t        auth_flavors[1];
+       char                    *client_address;
+
+       struct {
+               struct sockaddr_in      address;
+               unsigned int            program;
+               unsigned int            version;
+               unsigned short          port;
+               int                     protocol;
+       } mount_server;
+
+       struct {
+               struct sockaddr_in      address;
+               char                    *hostname;
+               char                    *export_path;
+               unsigned int            program;
+               int                     protocol;
+       } nfs_server;
+};
+
+enum {
+       /* Mount options that take no arguments */
+       Opt_soft, Opt_hard,
+       Opt_intr, Opt_nointr,
+       Opt_posix, Opt_noposix,
+       Opt_cto, Opt_nocto,
+       Opt_ac, Opt_noac,
+       Opt_lock, Opt_nolock,
+       Opt_v2, Opt_v3,
+       Opt_udp, Opt_tcp,
+       Opt_acl, Opt_noacl,
+       Opt_rdirplus, Opt_nordirplus,
+       Opt_sharecache, Opt_nosharecache,
+
+       /* Mount options that take integer arguments */
+       Opt_port,
+       Opt_rsize, Opt_wsize, Opt_bsize,
+       Opt_timeo, Opt_retrans,
+       Opt_acregmin, Opt_acregmax,
+       Opt_acdirmin, Opt_acdirmax,
+       Opt_actimeo,
+       Opt_namelen,
+       Opt_mountport,
+       Opt_mountprog, Opt_mountvers,
+       Opt_nfsprog, Opt_nfsvers,
+
+       /* Mount options that take string arguments */
+       Opt_sec, Opt_proto, Opt_mountproto,
+       Opt_addr, Opt_mounthost, Opt_clientaddr,
+
+       /* Mount options that are ignored */
+       Opt_userspace, Opt_deprecated,
+
+       Opt_err
+};
+
+static match_table_t nfs_mount_option_tokens = {
+       { Opt_userspace, "bg" },
+       { Opt_userspace, "fg" },
+       { Opt_soft, "soft" },
+       { Opt_hard, "hard" },
+       { Opt_intr, "intr" },
+       { Opt_nointr, "nointr" },
+       { Opt_posix, "posix" },
+       { Opt_noposix, "noposix" },
+       { Opt_cto, "cto" },
+       { Opt_nocto, "nocto" },
+       { Opt_ac, "ac" },
+       { Opt_noac, "noac" },
+       { Opt_lock, "lock" },
+       { Opt_nolock, "nolock" },
+       { Opt_v2, "v2" },
+       { Opt_v3, "v3" },
+       { Opt_udp, "udp" },
+       { Opt_tcp, "tcp" },
+       { Opt_acl, "acl" },
+       { Opt_noacl, "noacl" },
+       { Opt_rdirplus, "rdirplus" },
+       { Opt_nordirplus, "nordirplus" },
+       { Opt_sharecache, "sharecache" },
+       { Opt_nosharecache, "nosharecache" },
+
+       { Opt_port, "port=%u" },
+       { Opt_rsize, "rsize=%u" },
+       { Opt_wsize, "wsize=%u" },
+       { Opt_bsize, "bsize=%u" },
+       { Opt_timeo, "timeo=%u" },
+       { Opt_retrans, "retrans=%u" },
+       { Opt_acregmin, "acregmin=%u" },
+       { Opt_acregmax, "acregmax=%u" },
+       { Opt_acdirmin, "acdirmin=%u" },
+       { Opt_acdirmax, "acdirmax=%u" },
+       { Opt_actimeo, "actimeo=%u" },
+       { Opt_userspace, "retry=%u" },
+       { Opt_namelen, "namlen=%u" },
+       { Opt_mountport, "mountport=%u" },
+       { Opt_mountprog, "mountprog=%u" },
+       { Opt_mountvers, "mountvers=%u" },
+       { Opt_nfsprog, "nfsprog=%u" },
+       { Opt_nfsvers, "nfsvers=%u" },
+       { Opt_nfsvers, "vers=%u" },
+
+       { Opt_sec, "sec=%s" },
+       { Opt_proto, "proto=%s" },
+       { Opt_mountproto, "mountproto=%s" },
+       { Opt_addr, "addr=%s" },
+       { Opt_clientaddr, "clientaddr=%s" },
+       { Opt_mounthost, "mounthost=%s" },
+
+       { Opt_err, NULL }
+};
+
+enum {
+       Opt_xprt_udp, Opt_xprt_tcp,
+
+       Opt_xprt_err
+};
+
+static match_table_t nfs_xprt_protocol_tokens = {
+       { Opt_xprt_udp, "udp" },
+       { Opt_xprt_tcp, "tcp" },
+
+       { Opt_xprt_err, NULL }
+};
+
+enum {
+       Opt_sec_none, Opt_sec_sys,
+       Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
+       Opt_sec_lkey, Opt_sec_lkeyi, Opt_sec_lkeyp,
+       Opt_sec_spkm, Opt_sec_spkmi, Opt_sec_spkmp,
+
+       Opt_sec_err
+};
+
+static match_table_t nfs_secflavor_tokens = {
+       { Opt_sec_none, "none" },
+       { Opt_sec_none, "null" },
+       { Opt_sec_sys, "sys" },
+
+       { Opt_sec_krb5, "krb5" },
+       { Opt_sec_krb5i, "krb5i" },
+       { Opt_sec_krb5p, "krb5p" },
+
+       { Opt_sec_lkey, "lkey" },
+       { Opt_sec_lkeyi, "lkeyi" },
+       { Opt_sec_lkeyp, "lkeyp" },
+
+       { Opt_sec_err, NULL }
+};
+
+
 static void nfs_umount_begin(struct vfsmount *, int);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);
@@ -263,11 +425,11 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
                { RPC_AUTH_GSS_SPKM, "spkm" },
                { RPC_AUTH_GSS_SPKMI, "spkmi" },
                { RPC_AUTH_GSS_SPKMP, "spkmp" },
-               { -1, "unknown" }
+               { UINT_MAX, "unknown" }
        };
        int i;
 
-       for (i=0; sec_flavours[i].flavour != -1; i++) {
+       for (i = 0; sec_flavours[i].flavour != UINT_MAX; i++) {
                if (sec_flavours[i].flavour == flavour)
                        break;
        }
@@ -291,6 +453,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                { NFS_MOUNT_NONLM, ",nolock", "" },
                { NFS_MOUNT_NOACL, ",noacl", "" },
                { NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
+               { NFS_MOUNT_UNSHARED, ",nosharecache", ""},
                { 0, NULL, NULL }
        };
        const struct proc_nfs_info *nfs_infop;
@@ -430,87 +593,641 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
  */
 static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
 {
+       struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
+       struct rpc_clnt *rpc;
+
        shrink_submounts(vfsmnt, &nfs_automount_list);
+
+       if (!(flags & MNT_FORCE))
+               return;
+       /* -EIO all pending I/O */
+       rpc = server->client_acl;
+       if (!IS_ERR(rpc))
+               rpc_killall_tasks(rpc);
+       rpc = server->client;
+       if (!IS_ERR(rpc))
+               rpc_killall_tasks(rpc);
 }
 
 /*
- * Validate the NFS2/NFS3 mount data
- * - fills in the mount root filehandle
+ * Sanity-check a server address provided by the mount command
  */
-static int nfs_validate_mount_data(struct nfs_mount_data *data,
-                                  struct nfs_fh *mntfh)
+static int nfs_verify_server_address(struct sockaddr *addr)
 {
-       if (data == NULL) {
-               dprintk("%s: missing data argument\n", __FUNCTION__);
-               return -EINVAL;
+       switch (addr->sa_family) {
+       case AF_INET: {
+               struct sockaddr_in *sa = (struct sockaddr_in *) addr;
+               if (sa->sin_addr.s_addr != INADDR_ANY)
+                       return 1;
+               break;
+       }
        }
 
-       if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
-               dprintk("%s: bad mount version\n", __FUNCTION__);
-               return -EINVAL;
+       return 0;
+}
+
+/*
+ * Error-check and convert a string of mount options from user space into
+ * a data structure
+ */
+static int nfs_parse_mount_options(char *raw,
+                                  struct nfs_parsed_mount_data *mnt)
+{
+       char *p, *string;
+
+       if (!raw) {
+               dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
+               return 1;
        }
+       dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw);
 
-       switch (data->version) {
-               case 1:
-                       data->namlen = 0;
-               case 2:
-                       data->bsize  = 0;
-               case 3:
-                       if (data->flags & NFS_MOUNT_VER3) {
-                               dprintk("%s: mount structure version %d does not support NFSv3\n",
-                                               __FUNCTION__,
-                                               data->version);
-                               return -EINVAL;
+       while ((p = strsep(&raw, ",")) != NULL) {
+               substring_t args[MAX_OPT_ARGS];
+               int option, token;
+
+               if (!*p)
+                       continue;
+
+               dfprintk(MOUNT, "NFS:   parsing nfs mount option '%s'\n", p);
+
+               token = match_token(p, nfs_mount_option_tokens, args);
+               switch (token) {
+               case Opt_soft:
+                       mnt->flags |= NFS_MOUNT_SOFT;
+                       break;
+               case Opt_hard:
+                       mnt->flags &= ~NFS_MOUNT_SOFT;
+                       break;
+               case Opt_intr:
+                       mnt->flags |= NFS_MOUNT_INTR;
+                       break;
+               case Opt_nointr:
+                       mnt->flags &= ~NFS_MOUNT_INTR;
+                       break;
+               case Opt_posix:
+                       mnt->flags |= NFS_MOUNT_POSIX;
+                       break;
+               case Opt_noposix:
+                       mnt->flags &= ~NFS_MOUNT_POSIX;
+                       break;
+               case Opt_cto:
+                       mnt->flags &= ~NFS_MOUNT_NOCTO;
+                       break;
+               case Opt_nocto:
+                       mnt->flags |= NFS_MOUNT_NOCTO;
+                       break;
+               case Opt_ac:
+                       mnt->flags &= ~NFS_MOUNT_NOAC;
+                       break;
+               case Opt_noac:
+                       mnt->flags |= NFS_MOUNT_NOAC;
+                       break;
+               case Opt_lock:
+                       mnt->flags &= ~NFS_MOUNT_NONLM;
+                       break;
+               case Opt_nolock:
+                       mnt->flags |= NFS_MOUNT_NONLM;
+                       break;
+               case Opt_v2:
+                       mnt->flags &= ~NFS_MOUNT_VER3;
+                       break;
+               case Opt_v3:
+                       mnt->flags |= NFS_MOUNT_VER3;
+                       break;
+               case Opt_udp:
+                       mnt->flags &= ~NFS_MOUNT_TCP;
+                       mnt->nfs_server.protocol = IPPROTO_UDP;
+                       mnt->timeo = 7;
+                       mnt->retrans = 5;
+                       break;
+               case Opt_tcp:
+                       mnt->flags |= NFS_MOUNT_TCP;
+                       mnt->nfs_server.protocol = IPPROTO_TCP;
+                       mnt->timeo = 600;
+                       mnt->retrans = 2;
+                       break;
+               case Opt_acl:
+                       mnt->flags &= ~NFS_MOUNT_NOACL;
+                       break;
+               case Opt_noacl:
+                       mnt->flags |= NFS_MOUNT_NOACL;
+                       break;
+               case Opt_rdirplus:
+                       mnt->flags &= ~NFS_MOUNT_NORDIRPLUS;
+                       break;
+               case Opt_nordirplus:
+                       mnt->flags |= NFS_MOUNT_NORDIRPLUS;
+                       break;
+               case Opt_sharecache:
+                       mnt->flags &= ~NFS_MOUNT_UNSHARED;
+                       break;
+               case Opt_nosharecache:
+                       mnt->flags |= NFS_MOUNT_UNSHARED;
+                       break;
+
+               case Opt_port:
+                       if (match_int(args, &option))
+                               return 0;
+                       if (option < 0 || option > 65535)
+                               return 0;
+                       mnt->nfs_server.address.sin_port = htonl(option);
+                       break;
+               case Opt_rsize:
+                       if (match_int(args, &mnt->rsize))
+                               return 0;
+                       break;
+               case Opt_wsize:
+                       if (match_int(args, &mnt->wsize))
+                               return 0;
+                       break;
+               case Opt_bsize:
+                       if (match_int(args, &option))
+                               return 0;
+                       if (option < 0)
+                               return 0;
+                       mnt->bsize = option;
+                       break;
+               case Opt_timeo:
+                       if (match_int(args, &mnt->timeo))
+                               return 0;
+                       break;
+               case Opt_retrans:
+                       if (match_int(args, &mnt->retrans))
+                               return 0;
+                       break;
+               case Opt_acregmin:
+                       if (match_int(args, &mnt->acregmin))
+                               return 0;
+                       break;
+               case Opt_acregmax:
+                       if (match_int(args, &mnt->acregmax))
+                               return 0;
+                       break;
+               case Opt_acdirmin:
+                       if (match_int(args, &mnt->acdirmin))
+                               return 0;
+                       break;
+               case Opt_acdirmax:
+                       if (match_int(args, &mnt->acdirmax))
+                               return 0;
+                       break;
+               case Opt_actimeo:
+                       if (match_int(args, &option))
+                               return 0;
+                       if (option < 0)
+                               return 0;
+                       mnt->acregmin =
+                       mnt->acregmax =
+                       mnt->acdirmin =
+                       mnt->acdirmax = option;
+                       break;
+               case Opt_namelen:
+                       if (match_int(args, &mnt->namlen))
+                               return 0;
+                       break;
+               case Opt_mountport:
+                       if (match_int(args, &option))
+                               return 0;
+                       if (option < 0 || option > 65535)
+                               return 0;
+                       mnt->mount_server.port = option;
+                       break;
+               case Opt_mountprog:
+                       if (match_int(args, &option))
+                               return 0;
+                       if (option < 0)
+                               return 0;
+                       mnt->mount_server.program = option;
+                       break;
+               case Opt_mountvers:
+                       if (match_int(args, &option))
+                               return 0;
+                       if (option < 0)
+                               return 0;
+                       mnt->mount_server.version = option;
+                       break;
+               case Opt_nfsprog:
+                       if (match_int(args, &option))
+                               return 0;
+                       if (option < 0)
+                               return 0;
+                       mnt->nfs_server.program = option;
+                       break;
+               case Opt_nfsvers:
+                       if (match_int(args, &option))
+                               return 0;
+                       switch (option) {
+                       case 2:
+                               mnt->flags &= ~NFS_MOUNT_VER3;
+                               break;
+                       case 3:
+                               mnt->flags |= NFS_MOUNT_VER3;
+                               break;
+                       default:
+                               goto out_unrec_vers;
                        }
-                       data->root.size = NFS2_FHSIZE;
-                       memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
-               case 4:
-                       if (data->flags & NFS_MOUNT_SECFLAVOUR) {
-                               dprintk("%s: mount structure version %d does not support strong security\n",
-                                               __FUNCTION__,
-                                               data->version);
-                               return -EINVAL;
+                       break;
+
+               case Opt_sec:
+                       string = match_strdup(args);
+                       if (string == NULL)
+                               goto out_nomem;
+                       token = match_token(string, nfs_secflavor_tokens, args);
+                       kfree(string);
+
+                       /*
+                        * The flags setting is for v2/v3.  The flavor_len
+                        * setting is for v4.  v2/v3 also need to know the
+                        * difference between NULL and UNIX.
+                        */
+                       switch (token) {
+                       case Opt_sec_none:
+                               mnt->flags &= ~NFS_MOUNT_SECFLAVOUR;
+                               mnt->auth_flavor_len = 0;
+                               mnt->auth_flavors[0] = RPC_AUTH_NULL;
+                               break;
+                       case Opt_sec_sys:
+                               mnt->flags &= ~NFS_MOUNT_SECFLAVOUR;
+                               mnt->auth_flavor_len = 0;
+                               mnt->auth_flavors[0] = RPC_AUTH_UNIX;
+                               break;
+                       case Opt_sec_krb5:
+                               mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+                               mnt->auth_flavor_len = 1;
+                               mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5;
+                               break;
+                       case Opt_sec_krb5i:
+                               mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+                               mnt->auth_flavor_len = 1;
+                               mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5I;
+                               break;
+                       case Opt_sec_krb5p:
+                               mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+                               mnt->auth_flavor_len = 1;
+                               mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5P;
+                               break;
+                       case Opt_sec_lkey:
+                               mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+                               mnt->auth_flavor_len = 1;
+                               mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEY;
+                               break;
+                       case Opt_sec_lkeyi:
+                               mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+                               mnt->auth_flavor_len = 1;
+                               mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYI;
+                               break;
+                       case Opt_sec_lkeyp:
+                               mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+                               mnt->auth_flavor_len = 1;
+                               mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYP;
+                               break;
+                       case Opt_sec_spkm:
+                               mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+                               mnt->auth_flavor_len = 1;
+                               mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKM;
+                               break;
+                       case Opt_sec_spkmi:
+                               mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+                               mnt->auth_flavor_len = 1;
+                               mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMI;
+                               break;
+                       case Opt_sec_spkmp:
+                               mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+                               mnt->auth_flavor_len = 1;
+                               mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMP;
+                               break;
+                       default:
+                               goto out_unrec_sec;
                        }
-               case 5:
-                       memset(data->context, 0, sizeof(data->context));
-       }
+                       break;
+               case Opt_proto:
+                       string = match_strdup(args);
+                       if (string == NULL)
+                               goto out_nomem;
+                       token = match_token(string,
+                                           nfs_xprt_protocol_tokens, args);
+                       kfree(string);
+
+                       switch (token) {
+                       case Opt_udp:
+                               mnt->flags &= ~NFS_MOUNT_TCP;
+                               mnt->nfs_server.protocol = IPPROTO_UDP;
+                               mnt->timeo = 7;
+                               mnt->retrans = 5;
+                               break;
+                       case Opt_tcp:
+                               mnt->flags |= NFS_MOUNT_TCP;
+                               mnt->nfs_server.protocol = IPPROTO_TCP;
+                               mnt->timeo = 600;
+                               mnt->retrans = 2;
+                               break;
+                       default:
+                               goto out_unrec_xprt;
+                       }
+                       break;
+               case Opt_mountproto:
+                       string = match_strdup(args);
+                       if (string == NULL)
+                               goto out_nomem;
+                       token = match_token(string,
+                                           nfs_xprt_protocol_tokens, args);
+                       kfree(string);
+
+                       switch (token) {
+                       case Opt_udp:
+                               mnt->mount_server.protocol = IPPROTO_UDP;
+                               break;
+                       case Opt_tcp:
+                               mnt->mount_server.protocol = IPPROTO_TCP;
+                               break;
+                       default:
+                               goto out_unrec_xprt;
+                       }
+                       break;
+               case Opt_addr:
+                       string = match_strdup(args);
+                       if (string == NULL)
+                               goto out_nomem;
+                       mnt->nfs_server.address.sin_family = AF_INET;
+                       mnt->nfs_server.address.sin_addr.s_addr =
+                                                       in_aton(string);
+                       kfree(string);
+                       break;
+               case Opt_clientaddr:
+                       string = match_strdup(args);
+                       if (string == NULL)
+                               goto out_nomem;
+                       mnt->client_address = string;
+                       break;
+               case Opt_mounthost:
+                       string = match_strdup(args);
+                       if (string == NULL)
+                               goto out_nomem;
+                       mnt->mount_server.address.sin_family = AF_INET;
+                       mnt->mount_server.address.sin_addr.s_addr =
+                                                       in_aton(string);
+                       kfree(string);
+                       break;
 
-       /* Set the pseudoflavor */
-       if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
-               data->pseudoflavor = RPC_AUTH_UNIX;
+               case Opt_userspace:
+               case Opt_deprecated:
+                       break;
 
-#ifndef CONFIG_NFS_V3
-       /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
-       if (data->flags & NFS_MOUNT_VER3) {
-               dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
-               return -EPROTONOSUPPORT;
+               default:
+                       goto out_unknown;
+               }
        }
-#endif /* CONFIG_NFS_V3 */
 
-       /* We now require that the mount process passes the remote address */
-       if (data->addr.sin_addr.s_addr == INADDR_ANY) {
-               dprintk("%s: mount program didn't pass remote address!\n",
-                       __FUNCTION__);
-               return -EINVAL;
+       return 1;
+
+out_nomem:
+       printk(KERN_INFO "NFS: not enough memory to parse option\n");
+       return 0;
+
+out_unrec_vers:
+       printk(KERN_INFO "NFS: unrecognized NFS version number\n");
+       return 0;
+
+out_unrec_xprt:
+       printk(KERN_INFO "NFS: unrecognized transport protocol\n");
+       return 0;
+
+out_unrec_sec:
+       printk(KERN_INFO "NFS: unrecognized security flavor\n");
+       return 0;
+
+out_unknown:
+       printk(KERN_INFO "NFS: unknown mount option: %s\n", p);
+       return 0;
+}
+
+/*
+ * Use the remote server's MOUNT service to request the NFS file handle
+ * corresponding to the provided path.
+ */
+static int nfs_try_mount(struct nfs_parsed_mount_data *args,
+                        struct nfs_fh *root_fh)
+{
+       struct sockaddr_in sin;
+       int status;
+
+       if (args->mount_server.version == 0) {
+               if (args->flags & NFS_MOUNT_VER3)
+                       args->mount_server.version = NFS_MNT3_VERSION;
+               else
+                       args->mount_server.version = NFS_MNT_VERSION;
        }
 
-       /* Prepare the root filehandle */
-       if (data->flags & NFS_MOUNT_VER3)
-               mntfh->size = data->root.size;
+       /*
+        * Construct the mount server's address.
+        */
+       if (args->mount_server.address.sin_addr.s_addr != INADDR_ANY)
+               sin = args->mount_server.address;
        else
-               mntfh->size = NFS2_FHSIZE;
+               sin = args->nfs_server.address;
+       if (args->mount_server.port == 0) {
+               status = rpcb_getport_sync(&sin,
+                                          args->mount_server.program,
+                                          args->mount_server.version,
+                                          args->mount_server.protocol);
+               if (status < 0)
+                       goto out_err;
+               sin.sin_port = htons(status);
+       } else
+               sin.sin_port = htons(args->mount_server.port);
+
+       /*
+        * Now ask the mount server to map our export path
+        * to a file handle.
+        */
+       status = nfs_mount((struct sockaddr *) &sin,
+                          sizeof(sin),
+                          args->nfs_server.hostname,
+                          args->nfs_server.export_path,
+                          args->mount_server.version,
+                          args->mount_server.protocol,
+                          root_fh);
+       if (status < 0)
+               goto out_err;
+
+       return status;
 
-       if (mntfh->size > sizeof(mntfh->data)) {
-               dprintk("%s: invalid root filehandle\n", __FUNCTION__);
-               return -EINVAL;
+out_err:
+       dfprintk(MOUNT, "NFS: unable to contact server on host "
+                NIPQUAD_FMT "\n", NIPQUAD(sin.sin_addr.s_addr));
+       return status;
+}
+
+/*
+ * Validate the NFS2/NFS3 mount data
+ * - fills in the mount root filehandle
+ *
+ * For option strings, user space handles the following behaviors:
+ *
+ * + DNS: mapping server host name to IP address ("addr=" option)
+ *
+ * + failure mode: how to behave if a mount request can't be handled
+ *   immediately ("fg/bg" option)
+ *
+ * + retry: how often to retry a mount request ("retry=" option)
+ *
+ * + breaking back: trying proto=udp after proto=tcp, v2 after v3,
+ *   mountproto=tcp after mountproto=udp, and so on
+ *
+ * XXX: as far as I can tell, changing the NFS program number is not
+ *      supported in the NFS client.
+ */
+static int nfs_validate_mount_data(struct nfs_mount_data **options,
+                                  struct nfs_fh *mntfh,
+                                  const char *dev_name)
+{
+       struct nfs_mount_data *data = *options;
+
+       if (data == NULL)
+               goto out_no_data;
+
+       switch (data->version) {
+       case 1:
+               data->namlen = 0;
+       case 2:
+               data->bsize = 0;
+       case 3:
+               if (data->flags & NFS_MOUNT_VER3)
+                       goto out_no_v3;
+               data->root.size = NFS2_FHSIZE;
+               memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
+       case 4:
+               if (data->flags & NFS_MOUNT_SECFLAVOUR)
+                       goto out_no_sec;
+       case 5:
+               memset(data->context, 0, sizeof(data->context));
+       case 6:
+               if (data->flags & NFS_MOUNT_VER3)
+                       mntfh->size = data->root.size;
+               else
+                       mntfh->size = NFS2_FHSIZE;
+
+               if (mntfh->size > sizeof(mntfh->data))
+                       goto out_invalid_fh;
+
+               memcpy(mntfh->data, data->root.data, mntfh->size);
+               if (mntfh->size < sizeof(mntfh->data))
+                       memset(mntfh->data + mntfh->size, 0,
+                              sizeof(mntfh->data) - mntfh->size);
+               break;
+       default: {
+               unsigned int len;
+               char *c;
+               int status;
+               struct nfs_parsed_mount_data args = {
+                       .flags          = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP),
+                       .rsize          = NFS_MAX_FILE_IO_SIZE,
+                       .wsize          = NFS_MAX_FILE_IO_SIZE,
+                       .timeo          = 600,
+                       .retrans        = 2,
+                       .acregmin       = 3,
+                       .acregmax       = 60,
+                       .acdirmin       = 30,
+                       .acdirmax       = 60,
+                       .mount_server.protocol = IPPROTO_UDP,
+                       .mount_server.program = NFS_MNT_PROGRAM,
+                       .nfs_server.protocol = IPPROTO_TCP,
+                       .nfs_server.program = NFS_PROGRAM,
+               };
+
+               if (nfs_parse_mount_options((char *) *options, &args) == 0)
+                       return -EINVAL;
+
+               data = kzalloc(sizeof(*data), GFP_KERNEL);
+               if (data == NULL)
+                       return -ENOMEM;
+
+               /*
+                * NB: after this point, caller will free "data"
+                * if we return an error
+                */
+               *options = data;
+
+               c = strchr(dev_name, ':');
+               if (c == NULL)
+                       return -EINVAL;
+               len = c - dev_name - 1;
+               if (len > sizeof(data->hostname))
+                       return -EINVAL;
+               strncpy(data->hostname, dev_name, len);
+               args.nfs_server.hostname = data->hostname;
+
+               c++;
+               if (strlen(c) > NFS_MAXPATHLEN)
+                       return -EINVAL;
+               args.nfs_server.export_path = c;
+
+               status = nfs_try_mount(&args, mntfh);
+               if (status)
+                       return -EINVAL;
+
+               /*
+                * Translate to nfs_mount_data, which nfs_fill_super
+                * can deal with.
+                */
+               data->version           = 6;
+               data->flags             = args.flags;
+               data->rsize             = args.rsize;
+               data->wsize             = args.wsize;
+               data->timeo             = args.timeo;
+               data->retrans           = args.retrans;
+               data->acregmin          = args.acregmin;
+               data->acregmax          = args.acregmax;
+               data->acdirmin          = args.acdirmin;
+               data->acdirmax          = args.acdirmax;
+               data->addr              = args.nfs_server.address;
+               data->namlen            = args.namlen;
+               data->bsize             = args.bsize;
+               data->pseudoflavor      = args.auth_flavors[0];
+
+               break;
+               }
        }
 
-       memcpy(mntfh->data, data->root.data, mntfh->size);
-       if (mntfh->size < sizeof(mntfh->data))
-               memset(mntfh->data + mntfh->size, 0,
-                      sizeof(mntfh->data) - mntfh->size);
+       if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
+               data->pseudoflavor = RPC_AUTH_UNIX;
+
+#ifndef CONFIG_NFS_V3
+       if (data->flags & NFS_MOUNT_VER3)
+               goto out_v3_not_compiled;
+#endif /* !CONFIG_NFS_V3 */
+
+       if (!nfs_verify_server_address((struct sockaddr *) &data->addr))
+               goto out_no_address;
 
        return 0;
+
+out_no_data:
+       dfprintk(MOUNT, "NFS: mount program didn't pass any mount data\n");
+       return -EINVAL;
+
+out_no_v3:
+       dfprintk(MOUNT, "NFS: nfs_mount_data version %d does not support v3\n",
+                data->version);
+       return -EINVAL;
+
+out_no_sec:
+       dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n");
+       return -EINVAL;
+
+#ifndef CONFIG_NFS_V3
+out_v3_not_compiled:
+       dfprintk(MOUNT, "NFS: NFSv3 is not compiled into kernel\n");
+       return -EPROTONOSUPPORT;
+#endif /* !CONFIG_NFS_V3 */
+
+out_no_address:
+       dfprintk(MOUNT, "NFS: mount program didn't pass remote address\n");
+       return -EINVAL;
+
+out_invalid_fh:
+       dfprintk(MOUNT, "NFS: invalid root filehandle\n");
+       return -EINVAL;
 }
 
 /*
@@ -600,13 +1317,51 @@ static int nfs_compare_super(struct super_block *sb, void *data)
 {
        struct nfs_server *server = data, *old = NFS_SB(sb);
 
-       if (old->nfs_client != server->nfs_client)
+       if (memcmp(&old->nfs_client->cl_addr,
+                               &server->nfs_client->cl_addr,
+                               sizeof(old->nfs_client->cl_addr)) != 0)
+               return 0;
+       /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
+       if (old->flags & NFS_MOUNT_UNSHARED)
                return 0;
        if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
                return 0;
        return 1;
 }
 
+#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS)
+
+static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags)
+{
+       const struct nfs_server *a = s->s_fs_info;
+       const struct rpc_clnt *clnt_a = a->client;
+       const struct rpc_clnt *clnt_b = b->client;
+
+       if ((s->s_flags & NFS_MS_MASK) != (flags & NFS_MS_MASK))
+               goto Ebusy;
+       if (a->nfs_client != b->nfs_client)
+               goto Ebusy;
+       if (a->flags != b->flags)
+               goto Ebusy;
+       if (a->wsize != b->wsize)
+               goto Ebusy;
+       if (a->rsize != b->rsize)
+               goto Ebusy;
+       if (a->acregmin != b->acregmin)
+               goto Ebusy;
+       if (a->acregmax != b->acregmax)
+               goto Ebusy;
+       if (a->acdirmin != b->acdirmin)
+               goto Ebusy;
+       if (a->acdirmax != b->acdirmax)
+               goto Ebusy;
+       if (clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor)
+               goto Ebusy;
+       return 0;
+Ebusy:
+       return -EBUSY;
+}
+
 static int nfs_get_sb(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
 {
@@ -615,30 +1370,37 @@ static int nfs_get_sb(struct file_system_type *fs_type,
        struct nfs_fh mntfh;
        struct nfs_mount_data *data = raw_data;
        struct dentry *mntroot;
+       int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
        int error;
 
        /* Validate the mount data */
-       error = nfs_validate_mount_data(data, &mntfh);
+       error = nfs_validate_mount_data(&data, &mntfh, dev_name);
        if (error < 0)
-               return error;
+               goto out;
 
        /* Get a volume representation */
        server = nfs_create_server(data, &mntfh);
        if (IS_ERR(server)) {
                error = PTR_ERR(server);
-               goto out_err_noserver;
+               goto out;
        }
 
+       if (server->flags & NFS_MOUNT_UNSHARED)
+               compare_super = NULL;
+
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+       s = sget(fs_type, compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto out_err_nosb;
        }
 
        if (s->s_fs_info != server) {
+               error = nfs_compare_mount_options(s, server, flags);
                nfs_free_server(server);
                server = NULL;
+               if (error < 0)
+                       goto error_splat_super;
        }
 
        if (!s->s_root) {
@@ -656,17 +1418,21 @@ static int nfs_get_sb(struct file_system_type *fs_type,
        s->s_flags |= MS_ACTIVE;
        mnt->mnt_sb = s;
        mnt->mnt_root = mntroot;
-       return 0;
+       error = 0;
+
+out:
+       if (data != raw_data)
+               kfree(data);
+       return error;
 
 out_err_nosb:
        nfs_free_server(server);
-out_err_noserver:
-       return error;
+       goto out;
 
 error_splat_super:
        up_write(&s->s_umount);
        deactivate_super(s);
-       return error;
+       goto out;
 }
 
 /*
@@ -691,6 +1457,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
        struct super_block *s;
        struct nfs_server *server;
        struct dentry *mntroot;
+       int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
        int error;
 
        dprintk("--> nfs_xdev_get_sb()\n");
@@ -702,16 +1469,22 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
                goto out_err_noserver;
        }
 
+       if (server->flags & NFS_MOUNT_UNSHARED)
+               compare_super = NULL;
+
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto out_err_nosb;
        }
 
        if (s->s_fs_info != server) {
+               error = nfs_compare_mount_options(s, server, flags);
                nfs_free_server(server);
                server = NULL;
+               if (error < 0)
+                       goto error_splat_super;
        }
 
        if (!s->s_root) {
@@ -772,25 +1545,164 @@ static void nfs4_fill_super(struct super_block *sb)
        nfs_initialise_sb(sb);
 }
 
-static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
+/*
+ * Validate NFSv4 mount options
+ */
+static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
+                                   const char *dev_name,
+                                   struct sockaddr_in *addr,
+                                   rpc_authflavor_t *authflavour,
+                                   char **hostname,
+                                   char **mntpath,
+                                   char **ip_addr)
 {
-       void *p = NULL;
-
-       if (!src->len)
-               return ERR_PTR(-EINVAL);
-       if (src->len < maxlen)
-               maxlen = src->len;
-       if (dst == NULL) {
-               p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
-               if (p == NULL)
-                       return ERR_PTR(-ENOMEM);
-       }
-       if (copy_from_user(dst, src->data, maxlen)) {
-               kfree(p);
-               return ERR_PTR(-EFAULT);
+       struct nfs4_mount_data *data = *options;
+       char *c;
+
+       if (data == NULL)
+               goto out_no_data;
+
+       switch (data->version) {
+       case 1:
+               if (data->host_addrlen != sizeof(*addr))
+                       goto out_no_address;
+               if (copy_from_user(addr, data->host_addr, sizeof(*addr)))
+                       return -EFAULT;
+               if (addr->sin_port == 0)
+                       addr->sin_port = htons(NFS_PORT);
+               if (!nfs_verify_server_address((struct sockaddr *) addr))
+                       goto out_no_address;
+
+               switch (data->auth_flavourlen) {
+               case 0:
+                       *authflavour = RPC_AUTH_UNIX;
+                       break;
+               case 1:
+                       if (copy_from_user(authflavour, data->auth_flavours,
+                                          sizeof(*authflavour)))
+                               return -EFAULT;
+                       break;
+               default:
+                       goto out_inval_auth;
+               }
+
+               c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
+               if (IS_ERR(c))
+                       return PTR_ERR(c);
+               *hostname = c;
+
+               c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
+               if (IS_ERR(c))
+                       return PTR_ERR(c);
+               *mntpath = c;
+               dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *mntpath);
+
+               c = strndup_user(data->client_addr.data, 16);
+               if (IS_ERR(c))
+                       return PTR_ERR(c);
+               *ip_addr = c;
+
+               break;
+       default: {
+               unsigned int len;
+               struct nfs_parsed_mount_data args = {
+                       .rsize          = NFS_MAX_FILE_IO_SIZE,
+                       .wsize          = NFS_MAX_FILE_IO_SIZE,
+                       .timeo          = 600,
+                       .retrans        = 2,
+                       .acregmin       = 3,
+                       .acregmax       = 60,
+                       .acdirmin       = 30,
+                       .acdirmax       = 60,
+                       .nfs_server.protocol = IPPROTO_TCP,
+               };
+
+               if (nfs_parse_mount_options((char *) *options, &args) == 0)
+                       return -EINVAL;
+
+               if (!nfs_verify_server_address((struct sockaddr *)
+                                               &args.nfs_server.address))
+                       return -EINVAL;
+               *addr = args.nfs_server.address;
+
+               switch (args.auth_flavor_len) {
+               case 0:
+                       *authflavour = RPC_AUTH_UNIX;
+                       break;
+               case 1:
+                       *authflavour = (rpc_authflavor_t) args.auth_flavors[0];
+                       break;
+               default:
+                       goto out_inval_auth;
+               }
+
+               /*
+                * Translate to nfs4_mount_data, which nfs4_fill_super
+                * can deal with.
+                */
+               data = kzalloc(sizeof(*data), GFP_KERNEL);
+               if (data == NULL)
+                       return -ENOMEM;
+               *options = data;
+
+               data->version   = 1;
+               data->flags     = args.flags & NFS4_MOUNT_FLAGMASK;
+               data->rsize     = args.rsize;
+               data->wsize     = args.wsize;
+               data->timeo     = args.timeo;
+               data->retrans   = args.retrans;
+               data->acregmin  = args.acregmin;
+               data->acregmax  = args.acregmax;
+               data->acdirmin  = args.acdirmin;
+               data->acdirmax  = args.acdirmax;
+               data->proto     = args.nfs_server.protocol;
+
+               /*
+                * Split "dev_name" into "hostname:mntpath".
+                */
+               c = strchr(dev_name, ':');
+               if (c == NULL)
+                       return -EINVAL;
+               /* while calculating len, pretend ':' is '\0' */
+               len = c - dev_name;
+               if (len > NFS4_MAXNAMLEN)
+                       return -EINVAL;
+               *hostname = kzalloc(len, GFP_KERNEL);
+               if (*hostname == NULL)
+                       return -ENOMEM;
+               strncpy(*hostname, dev_name, len - 1);
+
+               c++;                    /* step over the ':' */
+               len = strlen(c);
+               if (len > NFS4_MAXPATHLEN)
+                       return -EINVAL;
+               *mntpath = kzalloc(len + 1, GFP_KERNEL);
+               if (*mntpath == NULL)
+                       return -ENOMEM;
+               strncpy(*mntpath, c, len);
+
+               dprintk("MNTPATH: %s\n", *mntpath);
+
+               *ip_addr = args.client_address;
+
+               break;
+               }
        }
-       dst[maxlen] = '\0';
-       return dst;
+
+       return 0;
+
+out_no_data:
+       dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n");
+       return -EINVAL;
+
+out_inval_auth:
+       dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n",
+                data->auth_flavourlen);
+       return -EINVAL;
+
+out_no_address:
+       dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
+       return -EINVAL;
 }
 
 /*
@@ -806,81 +1718,29 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
        rpc_authflavor_t authflavour;
        struct nfs_fh mntfh;
        struct dentry *mntroot;
-       char *mntpath = NULL, *hostname = NULL, ip_addr[16];
-       void *p;
+       char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
+       int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
        int error;
 
-       if (data == NULL) {
-               dprintk("%s: missing data argument\n", __FUNCTION__);
-               return -EINVAL;
-       }
-       if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
-               dprintk("%s: bad mount version\n", __FUNCTION__);
-               return -EINVAL;
-       }
-
-       /* We now require that the mount process passes the remote address */
-       if (data->host_addrlen != sizeof(addr))
-               return -EINVAL;
-
-       if (copy_from_user(&addr, data->host_addr, sizeof(addr)))
-               return -EFAULT;
-
-       if (addr.sin_family != AF_INET ||
-           addr.sin_addr.s_addr == INADDR_ANY
-           ) {
-               dprintk("%s: mount program didn't pass remote IP address!\n",
-                               __FUNCTION__);
-               return -EINVAL;
-       }
-       /* RFC3530: The default port for NFS is 2049 */
-       if (addr.sin_port == 0)
-               addr.sin_port = htons(NFS_PORT);
-
-       /* Grab the authentication type */
-       authflavour = RPC_AUTH_UNIX;
-       if (data->auth_flavourlen != 0) {
-               if (data->auth_flavourlen != 1) {
-                       dprintk("%s: Invalid number of RPC auth flavours %d.\n",
-                                       __FUNCTION__, data->auth_flavourlen);
-                       error = -EINVAL;
-                       goto out_err_noserver;
-               }
-
-               if (copy_from_user(&authflavour, data->auth_flavours,
-                                  sizeof(authflavour))) {
-                       error = -EFAULT;
-                       goto out_err_noserver;
-               }
-       }
-
-       p = nfs_copy_user_string(NULL, &data->hostname, 256);
-       if (IS_ERR(p))
-               goto out_err;
-       hostname = p;
-
-       p = nfs_copy_user_string(NULL, &data->mnt_path, 1024);
-       if (IS_ERR(p))
-               goto out_err;
-       mntpath = p;
-
-       dprintk("MNTPATH: %s\n", mntpath);
-
-       p = nfs_copy_user_string(ip_addr, &data->client_addr,
-                                sizeof(ip_addr) - 1);
-       if (IS_ERR(p))
-               goto out_err;
+       /* Validate the mount data */
+       error = nfs4_validate_mount_data(&data, dev_name, &addr, &authflavour,
+                                        &hostname, &mntpath, &ip_addr);
+       if (error < 0)
+               goto out;
 
        /* Get a volume representation */
        server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
                                    authflavour, &mntfh);
        if (IS_ERR(server)) {
                error = PTR_ERR(server);
-               goto out_err_noserver;
+               goto out;
        }
 
+       if (server->flags & NFS4_MOUNT_UNSHARED)
+               compare_super = NULL;
+
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+       s = sget(fs_type, compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto out_free;
@@ -906,25 +1766,22 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
        s->s_flags |= MS_ACTIVE;
        mnt->mnt_sb = s;
        mnt->mnt_root = mntroot;
+       error = 0;
+
+out:
+       kfree(ip_addr);
        kfree(mntpath);
        kfree(hostname);
-       return 0;
-
-out_err:
-       error = PTR_ERR(p);
-       goto out_err_noserver;
+       return error;
 
 out_free:
        nfs_free_server(server);
-out_err_noserver:
-       kfree(mntpath);
-       kfree(hostname);
-       return error;
+       goto out;
 
 error_splat_super:
        up_write(&s->s_umount);
        deactivate_super(s);
-       goto out_err_noserver;
+       goto out;
 }
 
 static void nfs4_kill_super(struct super_block *sb)
@@ -949,6 +1806,7 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
        struct super_block *s;
        struct nfs_server *server;
        struct dentry *mntroot;
+       int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
        int error;
 
        dprintk("--> nfs4_xdev_get_sb()\n");
@@ -960,8 +1818,11 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
                goto out_err_noserver;
        }
 
+       if (server->flags & NFS4_MOUNT_UNSHARED)
+               compare_super = NULL;
+
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto out_err_nosb;
@@ -1016,6 +1877,7 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
        struct nfs_server *server;
        struct dentry *mntroot;
        struct nfs_fh mntfh;
+       int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
        int error;
 
        dprintk("--> nfs4_referral_get_sb()\n");
@@ -1027,8 +1889,11 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
                goto out_err_noserver;
        }
 
+       if (server->flags & NFS4_MOUNT_UNSHARED)
+               compare_super = NULL;
+
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto out_err_nosb;
index af344a158e0103465ab632274e88b9583b69c5aa..73ac992ece85d2c33a1b02c368fe917110c63410 100644 (file)
@@ -117,19 +117,19 @@ static struct nfs_page *nfs_page_find_request_locked(struct page *page)
        if (PagePrivate(page)) {
                req = (struct nfs_page *)page_private(page);
                if (req != NULL)
-                       atomic_inc(&req->wb_count);
+                       kref_get(&req->wb_kref);
        }
        return req;
 }
 
 static struct nfs_page *nfs_page_find_request(struct page *page)
 {
+       struct inode *inode = page->mapping->host;
        struct nfs_page *req = NULL;
-       spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock;
 
-       spin_lock(req_lock);
+       spin_lock(&inode->i_lock);
        req = nfs_page_find_request_locked(page);
-       spin_unlock(req_lock);
+       spin_unlock(&inode->i_lock);
        return req;
 }
 
@@ -191,8 +191,6 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
        }
        /* Update file length */
        nfs_grow_file(page, offset, count);
-       /* Set the PG_uptodate flag? */
-       nfs_mark_uptodate(page, offset, count);
        nfs_unlock_request(req);
        return 0;
 }
@@ -253,16 +251,16 @@ static void nfs_end_page_writeback(struct page *page)
 static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
                                struct page *page)
 {
+       struct inode *inode = page->mapping->host;
+       struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_page *req;
-       struct nfs_inode *nfsi = NFS_I(page->mapping->host);
-       spinlock_t *req_lock = &nfsi->req_lock;
        int ret;
 
-       spin_lock(req_lock);
+       spin_lock(&inode->i_lock);
        for(;;) {
                req = nfs_page_find_request_locked(page);
                if (req == NULL) {
-                       spin_unlock(req_lock);
+                       spin_unlock(&inode->i_lock);
                        return 1;
                }
                if (nfs_lock_request_dontget(req))
@@ -272,28 +270,28 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
                 *       succeed provided that someone hasn't already marked the
                 *       request as dirty (in which case we don't care).
                 */
-               spin_unlock(req_lock);
+               spin_unlock(&inode->i_lock);
                ret = nfs_wait_on_request(req);
                nfs_release_request(req);
                if (ret != 0)
                        return ret;
-               spin_lock(req_lock);
+               spin_lock(&inode->i_lock);
        }
        if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) {
                /* This request is marked for commit */
-               spin_unlock(req_lock);
+               spin_unlock(&inode->i_lock);
                nfs_unlock_request(req);
                nfs_pageio_complete(pgio);
                return 1;
        }
        if (nfs_set_page_writeback(page) != 0) {
-               spin_unlock(req_lock);
+               spin_unlock(&inode->i_lock);
                BUG();
        }
        radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index,
-                       NFS_PAGE_TAG_WRITEBACK);
+                       NFS_PAGE_TAG_LOCKED);
        ret = test_bit(PG_NEED_FLUSH, &req->wb_flags);
-       spin_unlock(req_lock);
+       spin_unlock(&inode->i_lock);
        nfs_pageio_add_request(pgio, req);
        return ret;
 }
@@ -400,7 +398,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
        if (PageDirty(req->wb_page))
                set_bit(PG_NEED_FLUSH, &req->wb_flags);
        nfsi->npages++;
-       atomic_inc(&req->wb_count);
+       kref_get(&req->wb_kref);
        return 0;
 }
 
@@ -409,12 +407,12 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
  */
 static void nfs_inode_remove_request(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_context->dentry->d_inode;
+       struct inode *inode = req->wb_context->path.dentry->d_inode;
        struct nfs_inode *nfsi = NFS_I(inode);
 
        BUG_ON (!NFS_WBACK_BUSY(req));
 
-       spin_lock(&nfsi->req_lock);
+       spin_lock(&inode->i_lock);
        set_page_private(req->wb_page, 0);
        ClearPagePrivate(req->wb_page);
        radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
@@ -422,11 +420,11 @@ static void nfs_inode_remove_request(struct nfs_page *req)
                __set_page_dirty_nobuffers(req->wb_page);
        nfsi->npages--;
        if (!nfsi->npages) {
-               spin_unlock(&nfsi->req_lock);
+               spin_unlock(&inode->i_lock);
                nfs_end_data_update(inode);
                iput(inode);
        } else
-               spin_unlock(&nfsi->req_lock);
+               spin_unlock(&inode->i_lock);
        nfs_clear_request(req);
        nfs_release_request(req);
 }
@@ -457,14 +455,16 @@ nfs_dirty_request(struct nfs_page *req)
 static void
 nfs_mark_request_commit(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_context->dentry->d_inode;
+       struct inode *inode = req->wb_context->path.dentry->d_inode;
        struct nfs_inode *nfsi = NFS_I(inode);
 
-       spin_lock(&nfsi->req_lock);
-       nfs_list_add_request(req, &nfsi->commit);
+       spin_lock(&inode->i_lock);
        nfsi->ncommit++;
        set_bit(PG_NEED_COMMIT, &(req)->wb_flags);
-       spin_unlock(&nfsi->req_lock);
+       radix_tree_tag_set(&nfsi->nfs_page_tree,
+                       req->wb_index,
+                       NFS_PAGE_TAG_COMMIT);
+       spin_unlock(&inode->i_lock);
        inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
        __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
 }
@@ -526,18 +526,18 @@ static int nfs_wait_on_requests_locked(struct inode *inode, pgoff_t idx_start, u
                idx_end = idx_start + npages - 1;
 
        next = idx_start;
-       while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) {
+       while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_LOCKED)) {
                if (req->wb_index > idx_end)
                        break;
 
                next = req->wb_index + 1;
                BUG_ON(!NFS_WBACK_BUSY(req));
 
-               atomic_inc(&req->wb_count);
-               spin_unlock(&nfsi->req_lock);
+               kref_get(&req->wb_kref);
+               spin_unlock(&inode->i_lock);
                error = nfs_wait_on_request(req);
                nfs_release_request(req);
-               spin_lock(&nfsi->req_lock);
+               spin_lock(&inode->i_lock);
                if (error < 0)
                        return error;
                res++;
@@ -577,10 +577,9 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, u
        int res = 0;
 
        if (nfsi->ncommit != 0) {
-               res = nfs_scan_list(nfsi, &nfsi->commit, dst, idx_start, npages);
+               res = nfs_scan_list(nfsi, dst, idx_start, npages,
+                               NFS_PAGE_TAG_COMMIT);
                nfsi->ncommit -= res;
-               if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
-                       printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
        }
        return res;
 }
@@ -603,7 +602,6 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
 {
        struct address_space *mapping = page->mapping;
        struct inode *inode = mapping->host;
-       struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_page         *req, *new = NULL;
        pgoff_t         rqend, end;
 
@@ -613,13 +611,13 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
                /* Loop over all inode entries and see if we find
                 * A request for the page we wish to update
                 */
-               spin_lock(&nfsi->req_lock);
+               spin_lock(&inode->i_lock);
                req = nfs_page_find_request_locked(page);
                if (req) {
                        if (!nfs_lock_request_dontget(req)) {
                                int error;
 
-                               spin_unlock(&nfsi->req_lock);
+                               spin_unlock(&inode->i_lock);
                                error = nfs_wait_on_request(req);
                                nfs_release_request(req);
                                if (error < 0) {
@@ -629,7 +627,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
                                }
                                continue;
                        }
-                       spin_unlock(&nfsi->req_lock);
+                       spin_unlock(&inode->i_lock);
                        if (new)
                                nfs_release_request(new);
                        break;
@@ -640,14 +638,14 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
                        nfs_lock_request_dontget(new);
                        error = nfs_inode_add_request(inode, new);
                        if (error) {
-                               spin_unlock(&nfsi->req_lock);
+                               spin_unlock(&inode->i_lock);
                                nfs_unlock_request(new);
                                return ERR_PTR(error);
                        }
-                       spin_unlock(&nfsi->req_lock);
+                       spin_unlock(&inode->i_lock);
                        return new;
                }
-               spin_unlock(&nfsi->req_lock);
+               spin_unlock(&inode->i_lock);
 
                new = nfs_create_request(ctx, inode, page, offset, bytes);
                if (IS_ERR(new))
@@ -751,12 +749,17 @@ int nfs_updatepage(struct file *file, struct page *page,
 static void nfs_writepage_release(struct nfs_page *req)
 {
 
-       if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) {
+       if (PageError(req->wb_page)) {
+               nfs_end_page_writeback(req->wb_page);
+               nfs_inode_remove_request(req);
+       } else if (!nfs_reschedule_unstable_write(req)) {
+               /* Set the PG_uptodate flag */
+               nfs_mark_uptodate(req->wb_page, req->wb_pgbase, req->wb_bytes);
                nfs_end_page_writeback(req->wb_page);
                nfs_inode_remove_request(req);
        } else
                nfs_end_page_writeback(req->wb_page);
-       nfs_clear_page_writeback(req);
+       nfs_clear_page_tag_locked(req);
 }
 
 static inline int flush_task_priority(int how)
@@ -786,7 +789,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
         * NB: take care not to mess about with data->commit et al. */
 
        data->req = req;
-       data->inode = inode = req->wb_context->dentry->d_inode;
+       data->inode = inode = req->wb_context->path.dentry->d_inode;
        data->cred = req->wb_context->cred;
 
        data->args.fh     = NFS_FH(inode);
@@ -885,7 +888,7 @@ out_bad:
        }
        nfs_redirty_request(req);
        nfs_end_page_writeback(req->wb_page);
-       nfs_clear_page_writeback(req);
+       nfs_clear_page_tag_locked(req);
        return -ENOMEM;
 }
 
@@ -928,7 +931,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
                nfs_list_remove_request(req);
                nfs_redirty_request(req);
                nfs_end_page_writeback(req->wb_page);
-               nfs_clear_page_writeback(req);
+               nfs_clear_page_tag_locked(req);
        }
        return -ENOMEM;
 }
@@ -954,8 +957,8 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
        struct page             *page = req->wb_page;
 
        dprintk("NFS: write (%s/%Ld %d@%Ld)",
-               req->wb_context->dentry->d_inode->i_sb->s_id,
-               (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+               req->wb_context->path.dentry->d_inode->i_sb->s_id,
+               (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
                req->wb_bytes,
                (long long)req_offset(req));
 
@@ -970,9 +973,9 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
        }
 
        if (nfs_write_need_commit(data)) {
-               spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock;
+               struct inode *inode = page->mapping->host;
 
-               spin_lock(req_lock);
+               spin_lock(&inode->i_lock);
                if (test_bit(PG_NEED_RESCHED, &req->wb_flags)) {
                        /* Do nothing we need to resend the writes */
                } else if (!test_and_set_bit(PG_NEED_COMMIT, &req->wb_flags)) {
@@ -983,7 +986,7 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
                        clear_bit(PG_NEED_COMMIT, &req->wb_flags);
                        dprintk(" server reboot detected\n");
                }
-               spin_unlock(req_lock);
+               spin_unlock(&inode->i_lock);
        } else
                dprintk(" OK\n");
 
@@ -1020,8 +1023,8 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
                page = req->wb_page;
 
                dprintk("NFS: write (%s/%Ld %d@%Ld)",
-                       req->wb_context->dentry->d_inode->i_sb->s_id,
-                       (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+                       req->wb_context->path.dentry->d_inode->i_sb->s_id,
+                       (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
                        req->wb_bytes,
                        (long long)req_offset(req));
 
@@ -1039,12 +1042,14 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
                        dprintk(" marked for commit\n");
                        goto next;
                }
+               /* Set the PG_uptodate flag? */
+               nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes);
                dprintk(" OK\n");
 remove_request:
                nfs_end_page_writeback(page);
                nfs_inode_remove_request(req);
        next:
-               nfs_clear_page_writeback(req);
+               nfs_clear_page_tag_locked(req);
        }
 }
 
@@ -1157,7 +1162,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
 
        list_splice_init(head, &data->pages);
        first = nfs_list_entry(data->pages.next);
-       inode = first->wb_context->dentry->d_inode;
+       inode = first->wb_context->path.dentry->d_inode;
 
        data->inode       = inode;
        data->cred        = first->wb_context->cred;
@@ -1207,7 +1212,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
                nfs_list_remove_request(req);
                nfs_mark_request_commit(req);
                dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
-               nfs_clear_page_writeback(req);
+               nfs_clear_page_tag_locked(req);
        }
        return -ENOMEM;
 }
@@ -1234,8 +1239,8 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
                dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
 
                dprintk("NFS: commit (%s/%Ld %d@%Ld)",
-                       req->wb_context->dentry->d_inode->i_sb->s_id,
-                       (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+                       req->wb_context->path.dentry->d_inode->i_sb->s_id,
+                       (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
                        req->wb_bytes,
                        (long long)req_offset(req));
                if (task->tk_status < 0) {
@@ -1249,6 +1254,9 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
                 * returned by the server against all stored verfs. */
                if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) {
                        /* We have a match */
+                       /* Set the PG_uptodate flag */
+                       nfs_mark_uptodate(req->wb_page, req->wb_pgbase,
+                                       req->wb_bytes);
                        nfs_inode_remove_request(req);
                        dprintk(" OK\n");
                        goto next;
@@ -1257,7 +1265,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
                dprintk(" mismatch\n");
                nfs_redirty_request(req);
        next:
-               nfs_clear_page_writeback(req);
+               nfs_clear_page_tag_locked(req);
        }
 }
 
@@ -1268,13 +1276,12 @@ static const struct rpc_call_ops nfs_commit_ops = {
 
 int nfs_commit_inode(struct inode *inode, int how)
 {
-       struct nfs_inode *nfsi = NFS_I(inode);
        LIST_HEAD(head);
        int res;
 
-       spin_lock(&nfsi->req_lock);
+       spin_lock(&inode->i_lock);
        res = nfs_scan_commit(inode, &head, 0, 0);
-       spin_unlock(&nfsi->req_lock);
+       spin_unlock(&inode->i_lock);
        if (res) {
                int error = nfs_commit_list(inode, &head, how);
                if (error < 0)
@@ -1292,7 +1299,6 @@ static inline int nfs_commit_list(struct inode *inode, struct list_head *head, i
 long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_control *wbc, int how)
 {
        struct inode *inode = mapping->host;
-       struct nfs_inode *nfsi = NFS_I(inode);
        pgoff_t idx_start, idx_end;
        unsigned int npages = 0;
        LIST_HEAD(head);
@@ -1314,7 +1320,7 @@ long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_contr
                }
        }
        how &= ~FLUSH_NOCOMMIT;
-       spin_lock(&nfsi->req_lock);
+       spin_lock(&inode->i_lock);
        do {
                ret = nfs_wait_on_requests_locked(inode, idx_start, npages);
                if (ret != 0)
@@ -1325,18 +1331,19 @@ long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_contr
                if (pages == 0)
                        break;
                if (how & FLUSH_INVALIDATE) {
-                       spin_unlock(&nfsi->req_lock);
+                       spin_unlock(&inode->i_lock);
                        nfs_cancel_commit_list(&head);
                        ret = pages;
-                       spin_lock(&nfsi->req_lock);
+                       spin_lock(&inode->i_lock);
                        continue;
                }
                pages += nfs_scan_commit(inode, &head, 0, 0);
-               spin_unlock(&nfsi->req_lock);
+               spin_unlock(&inode->i_lock);
                ret = nfs_commit_list(inode, &head, how);
-               spin_lock(&nfsi->req_lock);
+               spin_lock(&inode->i_lock);
+
        } while (ret >= 0);
-       spin_unlock(&nfsi->req_lock);
+       spin_unlock(&inode->i_lock);
        return ret;
 }
 
@@ -1430,7 +1437,6 @@ int nfs_set_page_dirty(struct page *page)
 {
        struct address_space *mapping = page->mapping;
        struct inode *inode;
-       spinlock_t *req_lock;
        struct nfs_page *req;
        int ret;
 
@@ -1439,18 +1445,17 @@ int nfs_set_page_dirty(struct page *page)
        inode = mapping->host;
        if (!inode)
                goto out_raced;
-       req_lock = &NFS_I(inode)->req_lock;
-       spin_lock(req_lock);
+       spin_lock(&inode->i_lock);
        req = nfs_page_find_request_locked(page);
        if (req != NULL) {
                /* Mark any existing write requests for flushing */
                ret = !test_and_set_bit(PG_NEED_FLUSH, &req->wb_flags);
-               spin_unlock(req_lock);
+               spin_unlock(&inode->i_lock);
                nfs_release_request(req);
                return ret;
        }
        ret = __set_page_dirty_nobuffers(page);
-       spin_unlock(req_lock);
+       spin_unlock(&inode->i_lock);
        return ret;
 out_raced:
        return !TestSetPageDirty(page);
index 864090edc28b2faebb78da68b085208518150cdb..5443c52b57aa015456ec0aa407f4fb11b351c997 100644 (file)
@@ -394,7 +394,6 @@ nfsd4_probe_callback(struct nfs4_client *clp)
                .rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
                .rpc_argp       = clp,
        };
-       char clientname[16];
        int status;
 
        if (atomic_read(&cb->cb_set))
@@ -417,11 +416,6 @@ nfsd4_probe_callback(struct nfs4_client *clp)
        memset(program->stats, 0, sizeof(cb->cb_stat));
        program->stats->program = program;
 
-       /* Just here to make some printk's more useful: */
-       snprintf(clientname, sizeof(clientname),
-               "%u.%u.%u.%u", NIPQUAD(addr.sin_addr));
-       args.servername = clientname;
-
        /* Create RPC client */
        cb->cb_client = rpc_create(&args);
        if (IS_ERR(cb->cb_client)) {
@@ -429,29 +423,23 @@ nfsd4_probe_callback(struct nfs4_client *clp)
                goto out_err;
        }
 
-       /* Kick rpciod, put the call on the wire. */
-       if (rpciod_up() != 0)
-               goto out_clnt;
-
        /* the task holds a reference to the nfs4_client struct */
        atomic_inc(&clp->cl_count);
 
        msg.rpc_cred = nfsd4_lookupcred(clp,0);
        if (IS_ERR(msg.rpc_cred))
-               goto out_rpciod;
+               goto out_release_clp;
        status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL);
        put_rpccred(msg.rpc_cred);
 
        if (status != 0) {
                dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n");
-               goto out_rpciod;
+               goto out_release_clp;
        }
        return;
 
-out_rpciod:
+out_release_clp:
        atomic_dec(&clp->cl_count);
-       rpciod_down();
-out_clnt:
        rpc_shutdown_client(cb->cb_client);
 out_err:
        cb->cb_client = NULL;
index 3cc8ce422ab1a245a746cc15401be505031f17c2..8c52913d7cb6ddfb461ac3e72c3c1ab1f93c8f53 100644 (file)
@@ -378,7 +378,6 @@ shutdown_callback_client(struct nfs4_client *clp)
        if (clnt) {
                clp->cl_callback.cb_client = NULL;
                rpc_shutdown_client(clnt);
-               rpciod_down();
        }
 }
 
index 8604e35bd48e2d5966a244f1763f62def303dc0a..945b1cedde2bd2d0bd489b2faf74269f884166c2 100644 (file)
@@ -879,6 +879,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
                        .u.data         = rqstp,
                };
 
+               rqstp->rq_resused = 1;
                host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor);
        } else {
                oldfs = get_fs();
index 2b205f5d5790e73d281f6fbf7e298d2f7dc3b782..e9e042b93dbf520ed9dc2c4b64a0e1b96590c0a1 100644 (file)
@@ -74,7 +74,6 @@ struct mlog_attribute {
 #define define_mask(_name) {                   \
        .attr = {                               \
                .name = #_name,                 \
-               .owner = THIS_MODULE,           \
                .mode = S_IRUGO | S_IWUSR,      \
        },                                      \
        .mask = ML_##_name,                     \
index 9a3a058f355365405911c3f1173209cfac30150d..98e0b85a9bb268cd6677af538dc153a61af2f7f6 100644 (file)
@@ -397,7 +397,6 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len,
                static struct attribute addpartattr = {
                        .name = "whole_disk",
                        .mode = S_IRUSR | S_IRGRP | S_IROTH,
-                       .owner = THIS_MODULE,
                };
 
                sysfs_create_file(&p->kobj, &addpartattr);
index ed2ce995475c3f3cf6991de68cab9b38285ddc5d..6c9828651e6f5cdec78ce99d5169bb238c61f0ea 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/syscalls.h>
 #include <linux/uio.h>
+#include <linux/security.h>
 
 /*
  * Attempt to steal a page from a pipe buffer. This should perhaps go into
@@ -491,7 +492,7 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
 
        ret = 0;
        spliced = 0;
-       while (len) {
+       while (len && !spliced) {
                ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
 
                if (ret < 0)
@@ -961,6 +962,10 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
        if (unlikely(ret < 0))
                return ret;
 
+       ret = security_file_permission(out, MAY_WRITE);
+       if (unlikely(ret < 0))
+               return ret;
+
        return out->f_op->splice_write(pipe, out, ppos, len, flags);
 }
 
@@ -983,6 +988,10 @@ static long do_splice_to(struct file *in, loff_t *ppos,
        if (unlikely(ret < 0))
                return ret;
 
+       ret = security_file_permission(in, MAY_READ);
+       if (unlikely(ret < 0))
+               return ret;
+
        return in->f_op->splice_read(in, ppos, pipe, len, flags);
 }
 
@@ -1051,15 +1060,10 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
        sd->flags &= ~SPLICE_F_NONBLOCK;
 
        while (len) {
-               size_t read_len, max_read_len;
-
-               /*
-                * Do at most PIPE_BUFFERS pages worth of transfer:
-                */
-               max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
+               size_t read_len;
 
-               ret = do_splice_to(in, &sd->pos, pipe, max_read_len, flags);
-               if (unlikely(ret < 0))
+               ret = do_splice_to(in, &sd->pos, pipe, len, flags);
+               if (unlikely(ret <= 0))
                        goto out_release;
 
                read_len = ret;
@@ -1071,26 +1075,17 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
                 * could get stuck data in the internal pipe:
                 */
                ret = actor(pipe, sd);
-               if (unlikely(ret < 0))
+               if (unlikely(ret <= 0))
                        goto out_release;
 
                bytes += ret;
                len -= ret;
 
-               /*
-                * In nonblocking mode, if we got back a short read then
-                * that was due to either an IO error or due to the
-                * pagecache entry not being there. In the IO error case
-                * the _next_ splice attempt will produce a clean IO error
-                * return value (not a short read), so in both cases it's
-                * correct to break out of the loop here:
-                */
-               if ((flags & SPLICE_F_NONBLOCK) && (read_len < max_read_len))
-                       break;
+               if (ret < read_len)
+                       goto out_release;
        }
 
        pipe->nrbufs = pipe->curbuf = 0;
-
        return bytes;
 
 out_release:
@@ -1152,10 +1147,12 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
                .pos            = *ppos,
                .u.file         = out,
        };
-       size_t ret;
+       long ret;
 
        ret = splice_direct_to_actor(in, &sd, direct_splice_actor);
-       *ppos = sd.pos;
+       if (ret > 0)
+               *ppos += ret;
+
        return ret;
 }
 
index d3b9f5f07db149a38ecb03d0a44370d365ffb5d5..135353f8a296773605fe9ca744fe4612fff0f678 100644 (file)
 
 #include "sysfs.h"
 
+struct bin_buffer {
+       struct mutex    mutex;
+       void            *buffer;
+       int             mmapped;
+};
+
 static int
 fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
 {
-       struct bin_attribute * attr = to_bin_attr(dentry);
-       struct kobject * kobj = to_kobj(dentry->d_parent);
+       struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+       struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+       struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+       int rc;
+
+       /* need attr_sd for attr, its parent for kobj */
+       if (!sysfs_get_active_two(attr_sd))
+               return -ENODEV;
 
-       if (!attr->read)
-               return -EIO;
+       rc = -EIO;
+       if (attr->read)
+               rc = attr->read(kobj, attr, buffer, off, count);
 
-       return attr->read(kobj, buffer, off, count);
+       sysfs_put_active_two(attr_sd);
+
+       return rc;
 }
 
 static ssize_t
-read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
+read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
 {
-       char *buffer = file->private_data;
+       struct bin_buffer *bb = file->private_data;
        struct dentry *dentry = file->f_path.dentry;
        int size = dentry->d_inode->i_size;
        loff_t offs = *off;
-       int ret;
-
-       if (count > PAGE_SIZE)
-               count = PAGE_SIZE;
+       int count = min_t(size_t, bytes, PAGE_SIZE);
 
        if (size) {
                if (offs > size)
@@ -51,43 +63,56 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
                        count = size - offs;
        }
 
-       ret = fill_read(dentry, buffer, offs, count);
-       if (ret < 0) 
-               return ret;
-       count = ret;
+       mutex_lock(&bb->mutex);
+
+       count = fill_read(dentry, bb->buffer, offs, count);
+       if (count < 0)
+               goto out_unlock;
 
-       if (copy_to_user(userbuf, buffer, count))
-               return -EFAULT;
+       if (copy_to_user(userbuf, bb->buffer, count)) {
+               count = -EFAULT;
+               goto out_unlock;
+       }
 
-       pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count);
+       pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
 
        *off = offs + count;
 
+ out_unlock:
+       mutex_unlock(&bb->mutex);
        return count;
 }
 
 static int
 flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
 {
-       struct bin_attribute *attr = to_bin_attr(dentry);
-       struct kobject *kobj = to_kobj(dentry->d_parent);
+       struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+       struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+       struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+       int rc;
+
+       /* need attr_sd for attr, its parent for kobj */
+       if (!sysfs_get_active_two(attr_sd))
+               return -ENODEV;
+
+       rc = -EIO;
+       if (attr->write)
+               rc = attr->write(kobj, attr, buffer, offset, count);
 
-       if (!attr->write)
-               return -EIO;
+       sysfs_put_active_two(attr_sd);
 
-       return attr->write(kobj, buffer, offset, count);
+       return rc;
 }
 
-static ssize_t write(struct file * file, const char __user * userbuf,
-                    size_t count, loff_t * off)
+static ssize_t write(struct file *file, const char __user *userbuf,
+                    size_t bytes, loff_t *off)
 {
-       char *buffer = file->private_data;
+       struct bin_buffer *bb = file->private_data;
        struct dentry *dentry = file->f_path.dentry;
        int size = dentry->d_inode->i_size;
        loff_t offs = *off;
+       int count = min_t(size_t, bytes, PAGE_SIZE);
 
-       if (count > PAGE_SIZE)
-               count = PAGE_SIZE;
        if (size) {
                if (offs > size)
                        return 0;
@@ -95,72 +120,100 @@ static ssize_t write(struct file * file, const char __user * userbuf,
                        count = size - offs;
        }
 
-       if (copy_from_user(buffer, userbuf, count))
-               return -EFAULT;
+       mutex_lock(&bb->mutex);
 
-       count = flush_write(dentry, buffer, offs, count);
+       if (copy_from_user(bb->buffer, userbuf, count)) {
+               count = -EFAULT;
+               goto out_unlock;
+       }
+
+       count = flush_write(dentry, bb->buffer, offs, count);
        if (count > 0)
                *off = offs + count;
+
+ out_unlock:
+       mutex_unlock(&bb->mutex);
        return count;
 }
 
 static int mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct dentry *dentry = file->f_path.dentry;
-       struct bin_attribute *attr = to_bin_attr(dentry);
-       struct kobject *kobj = to_kobj(dentry->d_parent);
+       struct bin_buffer *bb = file->private_data;
+       struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+       struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+       struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+       int rc;
+
+       mutex_lock(&bb->mutex);
+
+       /* need attr_sd for attr, its parent for kobj */
+       if (!sysfs_get_active_two(attr_sd))
+               return -ENODEV;
 
-       if (!attr->mmap)
-               return -EINVAL;
+       rc = -EINVAL;
+       if (attr->mmap)
+               rc = attr->mmap(kobj, attr, vma);
 
-       return attr->mmap(kobj, attr, vma);
+       if (rc == 0 && !bb->mmapped)
+               bb->mmapped = 1;
+       else
+               sysfs_put_active_two(attr_sd);
+
+       mutex_unlock(&bb->mutex);
+
+       return rc;
 }
 
 static int open(struct inode * inode, struct file * file)
 {
-       struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
-       struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
-       int error = -EINVAL;
-
-       if (!kobj || !attr)
-               goto Done;
+       struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+       struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+       struct bin_buffer *bb = NULL;
+       int error;
 
-       /* Grab the module reference for this attribute if we have one */
-       error = -ENODEV;
-       if (!try_module_get(attr->attr.owner)) 
-               goto Done;
+       /* need attr_sd for attr */
+       if (!sysfs_get_active(attr_sd))
+               return -ENODEV;
 
        error = -EACCES;
        if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap))
-               goto Error;
+               goto err_out;
        if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap))
-               goto Error;
+               goto err_out;
 
        error = -ENOMEM;
-       file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
-       if (!file->private_data)
-               goto Error;
-
-       error = 0;
-    goto Done;
-
- Error:
-       module_put(attr->attr.owner);
- Done:
-       if (error)
-               kobject_put(kobj);
+       bb = kzalloc(sizeof(*bb), GFP_KERNEL);
+       if (!bb)
+               goto err_out;
+
+       bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!bb->buffer)
+               goto err_out;
+
+       mutex_init(&bb->mutex);
+       file->private_data = bb;
+
+       /* open succeeded, put active reference and pin attr_sd */
+       sysfs_put_active(attr_sd);
+       sysfs_get(attr_sd);
+       return 0;
+
+ err_out:
+       sysfs_put_active(attr_sd);
+       kfree(bb);
        return error;
 }
 
 static int release(struct inode * inode, struct file * file)
 {
-       struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
-       struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
-       u8 * buffer = file->private_data;
-
-       kobject_put(kobj);
-       module_put(attr->attr.owner);
-       kfree(buffer);
+       struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+       struct bin_buffer *bb = file->private_data;
+
+       if (bb->mmapped)
+               sysfs_put_active_two(attr_sd);
+       sysfs_put(attr_sd);
+       kfree(bb->buffer);
+       kfree(bb);
        return 0;
 }
 
@@ -181,9 +234,9 @@ const struct file_operations bin_fops = {
 
 int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
 {
-       BUG_ON(!kobj || !kobj->dentry || !attr);
+       BUG_ON(!kobj || !kobj->sd || !attr);
 
-       return sysfs_add_file(kobj->dentry, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
+       return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
 }
 
 
@@ -195,7 +248,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
 
 void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
 {
-       if (sysfs_hash_and_remove(kobj->dentry, attr->attr.name) < 0) {
+       if (sysfs_hash_and_remove(kobj->sd, attr->attr.name) < 0) {
                printk(KERN_ERR "%s: "
                        "bad dentry or inode or no such file: \"%s\"\n",
                        __FUNCTION__, attr->attr.name);
index c4342a0199727b19fe832c4eaff371c0c8e1b9ee..aee966c44aacd1a0c7c89847cca9d0966595f62b 100644 (file)
 #include <linux/module.h>
 #include <linux/kobject.h>
 #include <linux/namei.h>
+#include <linux/idr.h>
+#include <linux/completion.h>
 #include <asm/semaphore.h>
 #include "sysfs.h"
 
-DECLARE_RWSEM(sysfs_rename_sem);
-spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_MUTEX(sysfs_mutex);
+spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED;
+
+static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_IDA(sysfs_ino_ida);
+
+/**
+ *     sysfs_link_sibling - link sysfs_dirent into sibling list
+ *     @sd: sysfs_dirent of interest
+ *
+ *     Link @sd into its sibling list which starts from
+ *     sd->s_parent->s_children.
+ *
+ *     Locking:
+ *     mutex_lock(sysfs_mutex)
+ */
+void sysfs_link_sibling(struct sysfs_dirent *sd)
+{
+       struct sysfs_dirent *parent_sd = sd->s_parent;
+
+       BUG_ON(sd->s_sibling);
+       sd->s_sibling = parent_sd->s_children;
+       parent_sd->s_children = sd;
+}
+
+/**
+ *     sysfs_unlink_sibling - unlink sysfs_dirent from sibling list
+ *     @sd: sysfs_dirent of interest
+ *
+ *     Unlink @sd from its sibling list which starts from
+ *     sd->s_parent->s_children.
+ *
+ *     Locking:
+ *     mutex_lock(sysfs_mutex)
+ */
+void sysfs_unlink_sibling(struct sysfs_dirent *sd)
+{
+       struct sysfs_dirent **pos;
+
+       for (pos = &sd->s_parent->s_children; *pos; pos = &(*pos)->s_sibling) {
+               if (*pos == sd) {
+                       *pos = sd->s_sibling;
+                       sd->s_sibling = NULL;
+                       break;
+               }
+       }
+}
+
+/**
+ *     sysfs_get_dentry - get dentry for the given sysfs_dirent
+ *     @sd: sysfs_dirent of interest
+ *
+ *     Get dentry for @sd.  Dentry is looked up if currently not
+ *     present.  This function climbs sysfs_dirent tree till it
+ *     reaches a sysfs_dirent with valid dentry attached and descends
+ *     down from there looking up dentry for each step.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     Pointer to found dentry on success, ERR_PTR() value on error.
+ */
+struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd)
+{
+       struct sysfs_dirent *cur;
+       struct dentry *parent_dentry, *dentry;
+       int i, depth;
+
+       /* Find the first parent which has valid s_dentry and get the
+        * dentry.
+        */
+       mutex_lock(&sysfs_mutex);
+ restart0:
+       spin_lock(&sysfs_assoc_lock);
+ restart1:
+       spin_lock(&dcache_lock);
+
+       dentry = NULL;
+       depth = 0;
+       cur = sd;
+       while (!cur->s_dentry || !cur->s_dentry->d_inode) {
+               if (cur->s_flags & SYSFS_FLAG_REMOVED) {
+                       dentry = ERR_PTR(-ENOENT);
+                       depth = 0;
+                       break;
+               }
+               cur = cur->s_parent;
+               depth++;
+       }
+       if (!IS_ERR(dentry))
+               dentry = dget_locked(cur->s_dentry);
+
+       spin_unlock(&dcache_lock);
+       spin_unlock(&sysfs_assoc_lock);
+
+       /* from the found dentry, look up depth times */
+       while (depth--) {
+               /* find and get depth'th ancestor */
+               for (cur = sd, i = 0; cur && i < depth; i++)
+                       cur = cur->s_parent;
+
+               /* This can happen if tree structure was modified due
+                * to move/rename.  Restart.
+                */
+               if (i != depth) {
+                       dput(dentry);
+                       goto restart0;
+               }
+
+               sysfs_get(cur);
+
+               mutex_unlock(&sysfs_mutex);
+
+               /* look it up */
+               parent_dentry = dentry;
+               dentry = lookup_one_len_kern(cur->s_name, parent_dentry,
+                                            strlen(cur->s_name));
+               dput(parent_dentry);
+
+               if (IS_ERR(dentry)) {
+                       sysfs_put(cur);
+                       return dentry;
+               }
+
+               mutex_lock(&sysfs_mutex);
+               spin_lock(&sysfs_assoc_lock);
+
+               /* This, again, can happen if tree structure has
+                * changed and we looked up the wrong thing.  Restart.
+                */
+               if (cur->s_dentry != dentry) {
+                       dput(dentry);
+                       sysfs_put(cur);
+                       goto restart1;
+               }
+
+               spin_unlock(&sysfs_assoc_lock);
+
+               sysfs_put(cur);
+       }
+
+       mutex_unlock(&sysfs_mutex);
+       return dentry;
+}
+
+/**
+ *     sysfs_get_active - get an active reference to sysfs_dirent
+ *     @sd: sysfs_dirent to get an active reference to
+ *
+ *     Get an active reference of @sd.  This function is noop if @sd
+ *     is NULL.
+ *
+ *     RETURNS:
+ *     Pointer to @sd on success, NULL on failure.
+ */
+struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
+{
+       if (unlikely(!sd))
+               return NULL;
+
+       while (1) {
+               int v, t;
+
+               v = atomic_read(&sd->s_active);
+               if (unlikely(v < 0))
+                       return NULL;
+
+               t = atomic_cmpxchg(&sd->s_active, v, v + 1);
+               if (likely(t == v))
+                       return sd;
+               if (t < 0)
+                       return NULL;
+
+               cpu_relax();
+       }
+}
+
+/**
+ *     sysfs_put_active - put an active reference to sysfs_dirent
+ *     @sd: sysfs_dirent to put an active reference to
+ *
+ *     Put an active reference to @sd.  This function is noop if @sd
+ *     is NULL.
+ */
+void sysfs_put_active(struct sysfs_dirent *sd)
+{
+       struct completion *cmpl;
+       int v;
+
+       if (unlikely(!sd))
+               return;
+
+       v = atomic_dec_return(&sd->s_active);
+       if (likely(v != SD_DEACTIVATED_BIAS))
+               return;
+
+       /* atomic_dec_return() is a mb(), we'll always see the updated
+        * sd->s_sibling.
+        */
+       cmpl = (void *)sd->s_sibling;
+       complete(cmpl);
+}
+
+/**
+ *     sysfs_get_active_two - get active references to sysfs_dirent and parent
+ *     @sd: sysfs_dirent of interest
+ *
+ *     Get active reference to @sd and its parent.  Parent's active
+ *     reference is grabbed first.  This function is noop if @sd is
+ *     NULL.
+ *
+ *     RETURNS:
+ *     Pointer to @sd on success, NULL on failure.
+ */
+struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd)
+{
+       if (sd) {
+               if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent)))
+                       return NULL;
+               if (unlikely(!sysfs_get_active(sd))) {
+                       sysfs_put_active(sd->s_parent);
+                       return NULL;
+               }
+       }
+       return sd;
+}
+
+/**
+ *     sysfs_put_active_two - put active references to sysfs_dirent and parent
+ *     @sd: sysfs_dirent of interest
+ *
+ *     Put active references to @sd and its parent.  This function is
+ *     noop if @sd is NULL.
+ */
+void sysfs_put_active_two(struct sysfs_dirent *sd)
+{
+       if (sd) {
+               sysfs_put_active(sd);
+               sysfs_put_active(sd->s_parent);
+       }
+}
+
+/**
+ *     sysfs_deactivate - deactivate sysfs_dirent
+ *     @sd: sysfs_dirent to deactivate
+ *
+ *     Deny new active references and drain existing ones.
+ */
+static void sysfs_deactivate(struct sysfs_dirent *sd)
+{
+       DECLARE_COMPLETION_ONSTACK(wait);
+       int v;
+
+       BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
+       sd->s_sibling = (void *)&wait;
+
+       /* atomic_add_return() is a mb(), put_active() will always see
+        * the updated sd->s_sibling.
+        */
+       v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);
+
+       if (v != SD_DEACTIVATED_BIAS)
+               wait_for_completion(&wait);
+
+       sd->s_sibling = NULL;
+}
+
+static int sysfs_alloc_ino(ino_t *pino)
+{
+       int ino, rc;
+
+ retry:
+       spin_lock(&sysfs_ino_lock);
+       rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino);
+       spin_unlock(&sysfs_ino_lock);
+
+       if (rc == -EAGAIN) {
+               if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
+                       goto retry;
+               rc = -ENOMEM;
+       }
+
+       *pino = ino;
+       return rc;
+}
+
+static void sysfs_free_ino(ino_t ino)
+{
+       spin_lock(&sysfs_ino_lock);
+       ida_remove(&sysfs_ino_ida, ino);
+       spin_unlock(&sysfs_ino_lock);
+}
+
+void release_sysfs_dirent(struct sysfs_dirent * sd)
+{
+       struct sysfs_dirent *parent_sd;
+
+ repeat:
+       /* Moving/renaming is always done while holding reference.
+        * sd->s_parent won't change beneath us.
+        */
+       parent_sd = sd->s_parent;
+
+       if (sysfs_type(sd) == SYSFS_KOBJ_LINK)
+               sysfs_put(sd->s_elem.symlink.target_sd);
+       if (sysfs_type(sd) & SYSFS_COPY_NAME)
+               kfree(sd->s_name);
+       kfree(sd->s_iattr);
+       sysfs_free_ino(sd->s_ino);
+       kmem_cache_free(sysfs_dir_cachep, sd);
+
+       sd = parent_sd;
+       if (sd && atomic_dec_and_test(&sd->s_count))
+               goto repeat;
+}
 
 static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
 {
        struct sysfs_dirent * sd = dentry->d_fsdata;
 
        if (sd) {
-               /* sd->s_dentry is protected with sysfs_lock.  This
-                * allows sysfs_drop_dentry() to dereference it.
+               /* sd->s_dentry is protected with sysfs_assoc_lock.
+                * This allows sysfs_drop_dentry() to dereference it.
                 */
-               spin_lock(&sysfs_lock);
+               spin_lock(&sysfs_assoc_lock);
 
                /* The dentry might have been deleted or another
                 * lookup could have happened updating sd->s_dentry to
@@ -32,7 +348,7 @@ static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
                 */
                if (sd->s_dentry == dentry)
                        sd->s_dentry = NULL;
-               spin_unlock(&sysfs_lock);
+               spin_unlock(&sysfs_assoc_lock);
                sysfs_put(sd);
        }
        iput(inode);
@@ -42,260 +358,402 @@ static struct dentry_operations sysfs_dentry_ops = {
        .d_iput         = sysfs_d_iput,
 };
 
-static unsigned int sysfs_inode_counter;
-ino_t sysfs_get_inum(void)
+struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
 {
-       if (unlikely(sysfs_inode_counter < 3))
-               sysfs_inode_counter = 3;
-       return sysfs_inode_counter++;
-}
+       char *dup_name = NULL;
+       struct sysfs_dirent *sd = NULL;
 
-/*
- * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent
- */
-static struct sysfs_dirent * __sysfs_new_dirent(void * element)
-{
-       struct sysfs_dirent * sd;
+       if (type & SYSFS_COPY_NAME) {
+               name = dup_name = kstrdup(name, GFP_KERNEL);
+               if (!name)
+                       goto err_out;
+       }
 
        sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
        if (!sd)
-               return NULL;
+               goto err_out;
+
+       if (sysfs_alloc_ino(&sd->s_ino))
+               goto err_out;
 
-       sd->s_ino = sysfs_get_inum();
        atomic_set(&sd->s_count, 1);
+       atomic_set(&sd->s_active, 0);
        atomic_set(&sd->s_event, 1);
-       INIT_LIST_HEAD(&sd->s_children);
-       INIT_LIST_HEAD(&sd->s_sibling);
-       sd->s_element = element;
+
+       sd->s_name = name;
+       sd->s_mode = mode;
+       sd->s_flags = type;
 
        return sd;
+
+ err_out:
+       kfree(dup_name);
+       kmem_cache_free(sysfs_dir_cachep, sd);
+       return NULL;
 }
 
-static void __sysfs_list_dirent(struct sysfs_dirent *parent_sd,
-                             struct sysfs_dirent *sd)
+/**
+ *     sysfs_attach_dentry - associate sysfs_dirent with dentry
+ *     @sd: target sysfs_dirent
+ *     @dentry: dentry to associate
+ *
+ *     Associate @sd with @dentry.  This is protected by
+ *     sysfs_assoc_lock to avoid race with sysfs_d_iput().
+ *
+ *     LOCKING:
+ *     mutex_lock(sysfs_mutex)
+ */
+static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry)
 {
-       if (sd)
-               list_add(&sd->s_sibling, &parent_sd->s_children);
+       dentry->d_op = &sysfs_dentry_ops;
+       dentry->d_fsdata = sysfs_get(sd);
+
+       /* protect sd->s_dentry against sysfs_d_iput */
+       spin_lock(&sysfs_assoc_lock);
+       sd->s_dentry = dentry;
+       spin_unlock(&sysfs_assoc_lock);
+
+       d_rehash(dentry);
 }
 
-static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent *parent_sd,
-                                               void * element)
+static int sysfs_ilookup_test(struct inode *inode, void *arg)
 {
-       struct sysfs_dirent *sd;
-       sd = __sysfs_new_dirent(element);
-       __sysfs_list_dirent(parent_sd, sd);
-       return sd;
+       struct sysfs_dirent *sd = arg;
+       return inode->i_ino == sd->s_ino;
 }
 
-/*
+/**
+ *     sysfs_addrm_start - prepare for sysfs_dirent add/remove
+ *     @acxt: pointer to sysfs_addrm_cxt to be used
+ *     @parent_sd: parent sysfs_dirent
  *
- * Return -EEXIST if there is already a sysfs element with the same name for
- * the same parent.
+ *     This function is called when the caller is about to add or
+ *     remove sysfs_dirent under @parent_sd.  This function acquires
+ *     sysfs_mutex, grabs inode for @parent_sd if available and lock
+ *     i_mutex of it.  @acxt is used to keep and pass context to
+ *     other addrm functions.
  *
- * called with parent inode's i_mutex held
+ *     LOCKING:
+ *     Kernel thread context (may sleep).  sysfs_mutex is locked on
+ *     return.  i_mutex of parent inode is locked on return if
+ *     available.
  */
-int sysfs_dirent_exist(struct sysfs_dirent *parent_sd,
-                         const unsigned char *new)
+void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
+                      struct sysfs_dirent *parent_sd)
 {
-       struct sysfs_dirent * sd;
+       struct inode *inode;
 
-       list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
-               if (sd->s_element) {
-                       const unsigned char *existing = sysfs_get_name(sd);
-                       if (strcmp(existing, new))
-                               continue;
-                       else
-                               return -EEXIST;
-               }
-       }
+       memset(acxt, 0, sizeof(*acxt));
+       acxt->parent_sd = parent_sd;
 
-       return 0;
+       /* Lookup parent inode.  inode initialization and I_NEW
+        * clearing are protected by sysfs_mutex.  By grabbing it and
+        * looking up with _nowait variant, inode state can be
+        * determined reliably.
+        */
+       mutex_lock(&sysfs_mutex);
+
+       inode = ilookup5_nowait(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
+                               parent_sd);
+
+       if (inode && !(inode->i_state & I_NEW)) {
+               /* parent inode available */
+               acxt->parent_inode = inode;
+
+               /* sysfs_mutex is below i_mutex in lock hierarchy.
+                * First, trylock i_mutex.  If fails, unlock
+                * sysfs_mutex and lock them in order.
+                */
+               if (!mutex_trylock(&inode->i_mutex)) {
+                       mutex_unlock(&sysfs_mutex);
+                       mutex_lock(&inode->i_mutex);
+                       mutex_lock(&sysfs_mutex);
+               }
+       } else
+               iput(inode);
 }
 
+/**
+ *     sysfs_add_one - add sysfs_dirent to parent
+ *     @acxt: addrm context to use
+ *     @sd: sysfs_dirent to be added
+ *
+ *     Get @acxt->parent_sd and set sd->s_parent to it and increment
+ *     nlink of parent inode if @sd is a directory.  @sd is NOT
+ *     linked into the children list of the parent.  The caller
+ *     should invoke sysfs_link_sibling() after this function
+ *     completes if @sd needs to be on the children list.
+ *
+ *     This function should be called between calls to
+ *     sysfs_addrm_start() and sysfs_addrm_finish() and should be
+ *     passed the same @acxt as passed to sysfs_addrm_start().
+ *
+ *     LOCKING:
+ *     Determined by sysfs_addrm_start().
+ */
+void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+{
+       sd->s_parent = sysfs_get(acxt->parent_sd);
+
+       if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
+               inc_nlink(acxt->parent_inode);
+
+       acxt->cnt++;
+}
 
-static struct sysfs_dirent *
-__sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type)
+/**
+ *     sysfs_remove_one - remove sysfs_dirent from parent
+ *     @acxt: addrm context to use
+ *     @sd: sysfs_dirent to be added
+ *
+ *     Mark @sd removed and drop nlink of parent inode if @sd is a
+ *     directory.  @sd is NOT unlinked from the children list of the
+ *     parent.  The caller is repsonsible for removing @sd from the
+ *     children list before calling this function.
+ *
+ *     This function should be called between calls to
+ *     sysfs_addrm_start() and sysfs_addrm_finish() and should be
+ *     passed the same @acxt as passed to sysfs_addrm_start().
+ *
+ *     LOCKING:
+ *     Determined by sysfs_addrm_start().
+ */
+void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
 {
-       struct sysfs_dirent * sd;
+       BUG_ON(sd->s_sibling || (sd->s_flags & SYSFS_FLAG_REMOVED));
 
-       sd = __sysfs_new_dirent(element);
-       if (!sd)
-               goto out;
+       sd->s_flags |= SYSFS_FLAG_REMOVED;
+       sd->s_sibling = acxt->removed;
+       acxt->removed = sd;
 
-       sd->s_mode = mode;
-       sd->s_type = type;
-       sd->s_dentry = dentry;
-       if (dentry) {
-               dentry->d_fsdata = sysfs_get(sd);
-               dentry->d_op = &sysfs_dentry_ops;
-       }
+       if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
+               drop_nlink(acxt->parent_inode);
 
-out:
-       return sd;
+       acxt->cnt++;
 }
 
-int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
-                       void * element, umode_t mode, int type)
+/**
+ *     sysfs_drop_dentry - drop dentry for the specified sysfs_dirent
+ *     @sd: target sysfs_dirent
+ *
+ *     Drop dentry for @sd.  @sd must have been unlinked from its
+ *     parent on entry to this function such that it can't be looked
+ *     up anymore.
+ *
+ *     @sd->s_dentry which is protected with sysfs_assoc_lock points
+ *     to the currently associated dentry but we're not holding a
+ *     reference to it and racing with dput().  Grab dcache_lock and
+ *     verify dentry before dropping it.  If @sd->s_dentry is NULL or
+ *     dput() beats us, no need to bother.
+ */
+static void sysfs_drop_dentry(struct sysfs_dirent *sd)
 {
-       struct sysfs_dirent *sd;
+       struct dentry *dentry = NULL;
+       struct inode *inode;
+
+       /* We're not holding a reference to ->s_dentry dentry but the
+        * field will stay valid as long as sysfs_assoc_lock is held.
+        */
+       spin_lock(&sysfs_assoc_lock);
+       spin_lock(&dcache_lock);
+
+       /* drop dentry if it's there and dput() didn't kill it yet */
+       if (sd->s_dentry && sd->s_dentry->d_inode) {
+               dentry = dget_locked(sd->s_dentry);
+               spin_lock(&dentry->d_lock);
+               __d_drop(dentry);
+               spin_unlock(&dentry->d_lock);
+       }
 
-       sd = __sysfs_make_dirent(dentry, element, mode, type);
-       __sysfs_list_dirent(parent_sd, sd);
+       spin_unlock(&dcache_lock);
+       spin_unlock(&sysfs_assoc_lock);
 
-       return sd ? 0 : -ENOMEM;
+       /* dentries for shadowed inodes are pinned, unpin */
+       if (dentry && sysfs_is_shadowed_inode(dentry->d_inode))
+               dput(dentry);
+       dput(dentry);
+
+       /* adjust nlink and update timestamp */
+       inode = ilookup(sysfs_sb, sd->s_ino);
+       if (inode) {
+               mutex_lock(&inode->i_mutex);
+
+               inode->i_ctime = CURRENT_TIME;
+               drop_nlink(inode);
+               if (sysfs_type(sd) == SYSFS_DIR)
+                       drop_nlink(inode);
+
+               mutex_unlock(&inode->i_mutex);
+               iput(inode);
+       }
 }
 
-static int init_dir(struct inode * inode)
+/**
+ *     sysfs_addrm_finish - finish up sysfs_dirent add/remove
+ *     @acxt: addrm context to finish up
+ *
+ *     Finish up sysfs_dirent add/remove.  Resources acquired by
+ *     sysfs_addrm_start() are released and removed sysfs_dirents are
+ *     cleaned up.  Timestamps on the parent inode are updated.
+ *
+ *     LOCKING:
+ *     All mutexes acquired by sysfs_addrm_start() are released.
+ *
+ *     RETURNS:
+ *     Number of added/removed sysfs_dirents since sysfs_addrm_start().
+ */
+int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
 {
-       inode->i_op = &sysfs_dir_inode_operations;
-       inode->i_fop = &sysfs_dir_operations;
+       /* release resources acquired by sysfs_addrm_start() */
+       mutex_unlock(&sysfs_mutex);
+       if (acxt->parent_inode) {
+               struct inode *inode = acxt->parent_inode;
 
-       /* directory inodes start off with i_nlink == 2 (for "." entry) */
-       inc_nlink(inode);
-       return 0;
+               /* if added/removed, update timestamps on the parent */
+               if (acxt->cnt)
+                       inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
+               mutex_unlock(&inode->i_mutex);
+               iput(inode);
+       }
+
+       /* kill removed sysfs_dirents */
+       while (acxt->removed) {
+               struct sysfs_dirent *sd = acxt->removed;
+
+               acxt->removed = sd->s_sibling;
+               sd->s_sibling = NULL;
+
+               sysfs_drop_dentry(sd);
+               sysfs_deactivate(sd);
+               sysfs_put(sd);
+       }
+
+       return acxt->cnt;
 }
 
-static int init_file(struct inode * inode)
+/**
+ *     sysfs_find_dirent - find sysfs_dirent with the given name
+ *     @parent_sd: sysfs_dirent to search under
+ *     @name: name to look for
+ *
+ *     Look for sysfs_dirent with name @name under @parent_sd.
+ *
+ *     LOCKING:
+ *     mutex_lock(sysfs_mutex)
+ *
+ *     RETURNS:
+ *     Pointer to sysfs_dirent if found, NULL if not.
+ */
+struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
+                                      const unsigned char *name)
 {
-       inode->i_size = PAGE_SIZE;
-       inode->i_fop = &sysfs_file_operations;
-       return 0;
+       struct sysfs_dirent *sd;
+
+       for (sd = parent_sd->s_children; sd; sd = sd->s_sibling)
+               if (sysfs_type(sd) && !strcmp(sd->s_name, name))
+                       return sd;
+       return NULL;
 }
 
-static int init_symlink(struct inode * inode)
+/**
+ *     sysfs_get_dirent - find and get sysfs_dirent with the given name
+ *     @parent_sd: sysfs_dirent to search under
+ *     @name: name to look for
+ *
+ *     Look for sysfs_dirent with name @name under @parent_sd and get
+ *     it if found.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).  Grabs sysfs_mutex.
+ *
+ *     RETURNS:
+ *     Pointer to sysfs_dirent if found, NULL if not.
+ */
+struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+                                     const unsigned char *name)
 {
-       inode->i_op = &sysfs_symlink_inode_operations;
-       return 0;
+       struct sysfs_dirent *sd;
+
+       mutex_lock(&sysfs_mutex);
+       sd = sysfs_find_dirent(parent_sd, name);
+       sysfs_get(sd);
+       mutex_unlock(&sysfs_mutex);
+
+       return sd;
 }
 
-static int create_dir(struct kobject * k, struct dentry * p,
-                     const char * n, struct dentry ** d)
+static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
+                     const char *name, struct sysfs_dirent **p_sd)
 {
-       int error;
        umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
+       struct sysfs_addrm_cxt acxt;
+       struct sysfs_dirent *sd;
 
-       mutex_lock(&p->d_inode->i_mutex);
-       *d = lookup_one_len(n, p, strlen(n));
-       if (!IS_ERR(*d)) {
-               if (sysfs_dirent_exist(p->d_fsdata, n))
-                       error = -EEXIST;
-               else
-                       error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
-                                                               SYSFS_DIR);
-               if (!error) {
-                       error = sysfs_create(*d, mode, init_dir);
-                       if (!error) {
-                               inc_nlink(p->d_inode);
-                               (*d)->d_op = &sysfs_dentry_ops;
-                               d_rehash(*d);
-                       }
-               }
-               if (error && (error != -EEXIST)) {
-                       struct sysfs_dirent *sd = (*d)->d_fsdata;
-                       if (sd) {
-                               list_del_init(&sd->s_sibling);
-                               sysfs_put(sd);
-                       }
-                       d_drop(*d);
-               }
-               dput(*d);
-       } else
-               error = PTR_ERR(*d);
-       mutex_unlock(&p->d_inode->i_mutex);
-       return error;
-}
+       /* allocate */
+       sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
+       if (!sd)
+               return -ENOMEM;
+       sd->s_elem.dir.kobj = kobj;
 
+       /* link in */
+       sysfs_addrm_start(&acxt, parent_sd);
+       if (!sysfs_find_dirent(parent_sd, name)) {
+               sysfs_add_one(&acxt, sd);
+               sysfs_link_sibling(sd);
+       }
+       if (sysfs_addrm_finish(&acxt)) {
+               *p_sd = sd;
+               return 0;
+       }
 
-int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d)
+       sysfs_put(sd);
+       return -EEXIST;
+}
+
+int sysfs_create_subdir(struct kobject *kobj, const char *name,
+                       struct sysfs_dirent **p_sd)
 {
-       return create_dir(k,k->dentry,n,d);
+       return create_dir(kobj, kobj->sd, name, p_sd);
 }
 
 /**
  *     sysfs_create_dir - create a directory for an object.
  *     @kobj:          object we're creating directory for. 
- *     @shadow_parent: parent parent object.
+ *     @shadow_parent: parent object.
  */
-
-int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent)
+int sysfs_create_dir(struct kobject *kobj,
+                    struct sysfs_dirent *shadow_parent_sd)
 {
-       struct dentry * dentry = NULL;
-       struct dentry * parent;
+       struct sysfs_dirent *parent_sd, *sd;
        int error = 0;
 
        BUG_ON(!kobj);
 
-       if (shadow_parent)
-               parent = shadow_parent;
+       if (shadow_parent_sd)
+               parent_sd = shadow_parent_sd;
        else if (kobj->parent)
-               parent = kobj->parent->dentry;
+               parent_sd = kobj->parent->sd;
        else if (sysfs_mount && sysfs_mount->mnt_sb)
-               parent = sysfs_mount->mnt_sb->s_root;
+               parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
        else
                return -EFAULT;
 
-       error = create_dir(kobj,parent,kobject_name(kobj),&dentry);
+       error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd);
        if (!error)
-               kobj->dentry = dentry;
+               kobj->sd = sd;
        return error;
 }
 
-/* attaches attribute's sysfs_dirent to the dentry corresponding to the
- * attribute file
- */
-static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
+static int sysfs_count_nlink(struct sysfs_dirent *sd)
 {
-       struct attribute * attr = NULL;
-       struct bin_attribute * bin_attr = NULL;
-       int (* init) (struct inode *) = NULL;
-       int error = 0;
-
-        if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) {
-                bin_attr = sd->s_element;
-                attr = &bin_attr->attr;
-        } else {
-                attr = sd->s_element;
-                init = init_file;
-        }
+       struct sysfs_dirent *child;
+       int nr = 0;
 
-       dentry->d_fsdata = sysfs_get(sd);
-       /* protect sd->s_dentry against sysfs_d_iput */
-       spin_lock(&sysfs_lock);
-       sd->s_dentry = dentry;
-       spin_unlock(&sysfs_lock);
-       error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
-       if (error) {
-               sysfs_put(sd);
-               return error;
-       }
-
-        if (bin_attr) {
-               dentry->d_inode->i_size = bin_attr->size;
-               dentry->d_inode->i_fop = &bin_fops;
-       }
-       dentry->d_op = &sysfs_dentry_ops;
-       d_rehash(dentry);
-
-       return 0;
-}
-
-static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
-{
-       int err = 0;
-
-       dentry->d_fsdata = sysfs_get(sd);
-       /* protect sd->s_dentry against sysfs_d_iput */
-       spin_lock(&sysfs_lock);
-       sd->s_dentry = dentry;
-       spin_unlock(&sysfs_lock);
-       err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
-       if (!err) {
-               dentry->d_op = &sysfs_dentry_ops;
-               d_rehash(dentry);
-       } else
-               sysfs_put(sd);
-
-       return err;
+       for (child = sd->s_children; child; child = child->s_sibling)
+               if (sysfs_type(child) == SYSFS_DIR)
+                       nr++;
+       return nr + 2;
 }
 
 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
@@ -303,24 +761,60 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
 {
        struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
        struct sysfs_dirent * sd;
-       int err = 0;
+       struct bin_attribute *bin_attr;
+       struct inode *inode;
+       int found = 0;
 
-       list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
-               if (sd->s_type & SYSFS_NOT_PINNED) {
-                       const unsigned char * name = sysfs_get_name(sd);
+       for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) {
+               if (sysfs_type(sd) &&
+                   !strcmp(sd->s_name, dentry->d_name.name)) {
+                       found = 1;
+                       break;
+               }
+       }
 
-                       if (strcmp(name, dentry->d_name.name))
-                               continue;
+       /* no such entry */
+       if (!found)
+               return NULL;
 
-                       if (sd->s_type & SYSFS_KOBJ_LINK)
-                               err = sysfs_attach_link(sd, dentry);
-                       else
-                               err = sysfs_attach_attr(sd, dentry);
+       /* attach dentry and inode */
+       inode = sysfs_get_inode(sd);
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+
+       mutex_lock(&sysfs_mutex);
+
+       if (inode->i_state & I_NEW) {
+               /* initialize inode according to type */
+               switch (sysfs_type(sd)) {
+               case SYSFS_DIR:
+                       inode->i_op = &sysfs_dir_inode_operations;
+                       inode->i_fop = &sysfs_dir_operations;
+                       inode->i_nlink = sysfs_count_nlink(sd);
+                       break;
+               case SYSFS_KOBJ_ATTR:
+                       inode->i_size = PAGE_SIZE;
+                       inode->i_fop = &sysfs_file_operations;
+                       break;
+               case SYSFS_KOBJ_BIN_ATTR:
+                       bin_attr = sd->s_elem.bin_attr.bin_attr;
+                       inode->i_size = bin_attr->size;
+                       inode->i_fop = &bin_fops;
                        break;
+               case SYSFS_KOBJ_LINK:
+                       inode->i_op = &sysfs_symlink_inode_operations;
+                       break;
+               default:
+                       BUG();
                }
        }
 
-       return ERR_PTR(err);
+       sysfs_instantiate(dentry, inode);
+       sysfs_attach_dentry(sd, dentry);
+
+       mutex_unlock(&sysfs_mutex);
+
+       return NULL;
 }
 
 const struct inode_operations sysfs_dir_inode_operations = {
@@ -328,58 +822,46 @@ const struct inode_operations sysfs_dir_inode_operations = {
        .setattr        = sysfs_setattr,
 };
 
-static void remove_dir(struct dentry * d)
+static void remove_dir(struct sysfs_dirent *sd)
 {
-       struct dentry * parent = dget(d->d_parent);
-       struct sysfs_dirent * sd;
-
-       mutex_lock(&parent->d_inode->i_mutex);
-       d_delete(d);
-       sd = d->d_fsdata;
-       list_del_init(&sd->s_sibling);
-       sysfs_put(sd);
-       if (d->d_inode)
-               simple_rmdir(parent->d_inode,d);
-
-       pr_debug(" o %s removing done (%d)\n",d->d_name.name,
-                atomic_read(&d->d_count));
+       struct sysfs_addrm_cxt acxt;
 
-       mutex_unlock(&parent->d_inode->i_mutex);
-       dput(parent);
+       sysfs_addrm_start(&acxt, sd->s_parent);
+       sysfs_unlink_sibling(sd);
+       sysfs_remove_one(&acxt, sd);
+       sysfs_addrm_finish(&acxt);
 }
 
-void sysfs_remove_subdir(struct dentry * d)
+void sysfs_remove_subdir(struct sysfs_dirent *sd)
 {
-       remove_dir(d);
+       remove_dir(sd);
 }
 
 
-static void __sysfs_remove_dir(struct dentry *dentry)
+static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
 {
-       struct sysfs_dirent * parent_sd;
-       struct sysfs_dirent * sd, * tmp;
+       struct sysfs_addrm_cxt acxt;
+       struct sysfs_dirent **pos;
 
-       dget(dentry);
-       if (!dentry)
+       if (!dir_sd)
                return;
 
-       pr_debug("sysfs %s: removing dir\n",dentry->d_name.name);
-       mutex_lock(&dentry->d_inode->i_mutex);
-       parent_sd = dentry->d_fsdata;
-       list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
-               if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED))
-                       continue;
-               list_del_init(&sd->s_sibling);
-               sysfs_drop_dentry(sd, dentry);
-               sysfs_put(sd);
+       pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
+       sysfs_addrm_start(&acxt, dir_sd);
+       pos = &dir_sd->s_children;
+       while (*pos) {
+               struct sysfs_dirent *sd = *pos;
+
+               if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) {
+                       *pos = sd->s_sibling;
+                       sd->s_sibling = NULL;
+                       sysfs_remove_one(&acxt, sd);
+               } else
+                       pos = &(*pos)->s_sibling;
        }
-       mutex_unlock(&dentry->d_inode->i_mutex);
+       sysfs_addrm_finish(&acxt);
 
-       remove_dir(dentry);
-       /**
-        * Drop reference from dget() on entrance.
-        */
-       dput(dentry);
+       remove_dir(dir_sd);
 }
 
 /**
@@ -393,102 +875,166 @@ static void __sysfs_remove_dir(struct dentry *dentry)
 
 void sysfs_remove_dir(struct kobject * kobj)
 {
-       __sysfs_remove_dir(kobj->dentry);
-       kobj->dentry = NULL;
+       struct sysfs_dirent *sd = kobj->sd;
+
+       spin_lock(&sysfs_assoc_lock);
+       kobj->sd = NULL;
+       spin_unlock(&sysfs_assoc_lock);
+
+       __sysfs_remove_dir(sd);
 }
 
-int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
+int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd,
                     const char *new_name)
 {
-       int error = 0;
-       struct dentry * new_dentry;
+       struct sysfs_dirent *sd = kobj->sd;
+       struct dentry *new_parent = NULL;
+       struct dentry *old_dentry = NULL, *new_dentry = NULL;
+       const char *dup_name = NULL;
+       int error;
 
-       if (!new_parent)
-               return -EFAULT;
+       /* get dentries */
+       old_dentry = sysfs_get_dentry(sd);
+       if (IS_ERR(old_dentry)) {
+               error = PTR_ERR(old_dentry);
+               goto out_dput;
+       }
 
-       down_write(&sysfs_rename_sem);
+       new_parent = sysfs_get_dentry(new_parent_sd);
+       if (IS_ERR(new_parent)) {
+               error = PTR_ERR(new_parent);
+               goto out_dput;
+       }
+
+       /* lock new_parent and get dentry for new name */
        mutex_lock(&new_parent->d_inode->i_mutex);
 
        new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name));
-       if (!IS_ERR(new_dentry)) {
-               /* By allowing two different directories with the
-                * same d_parent we allow this routine to move
-                * between different shadows of the same directory
-                */
-               if (kobj->dentry->d_parent->d_inode != new_parent->d_inode)
-                       return -EINVAL;
-               else if (new_dentry->d_parent->d_inode != new_parent->d_inode)
-                       error = -EINVAL;
-               else if (new_dentry == kobj->dentry)
-                       error = -EINVAL;
-               else if (!new_dentry->d_inode) {
-                       error = kobject_set_name(kobj, "%s", new_name);
-                       if (!error) {
-                               struct sysfs_dirent *sd, *parent_sd;
-
-                               d_add(new_dentry, NULL);
-                               d_move(kobj->dentry, new_dentry);
-
-                               sd = kobj->dentry->d_fsdata;
-                               parent_sd = new_parent->d_fsdata;
-
-                               list_del_init(&sd->s_sibling);
-                               list_add(&sd->s_sibling, &parent_sd->s_children);
-                       }
-                       else
-                               d_drop(new_dentry);
-               } else
-                       error = -EEXIST;
-               dput(new_dentry);
+       if (IS_ERR(new_dentry)) {
+               error = PTR_ERR(new_dentry);
+               goto out_unlock;
        }
-       mutex_unlock(&new_parent->d_inode->i_mutex);
-       up_write(&sysfs_rename_sem);
 
+       /* By allowing two different directories with the same
+        * d_parent we allow this routine to move between different
+        * shadows of the same directory
+        */
+       error = -EINVAL;
+       if (old_dentry->d_parent->d_inode != new_parent->d_inode ||
+           new_dentry->d_parent->d_inode != new_parent->d_inode ||
+           old_dentry == new_dentry)
+               goto out_unlock;
+
+       error = -EEXIST;
+       if (new_dentry->d_inode)
+               goto out_unlock;
+
+       /* rename kobject and sysfs_dirent */
+       error = -ENOMEM;
+       new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
+       if (!new_name)
+               goto out_drop;
+
+       error = kobject_set_name(kobj, "%s", new_name);
+       if (error)
+               goto out_drop;
+
+       dup_name = sd->s_name;
+       sd->s_name = new_name;
+
+       /* move under the new parent */
+       d_add(new_dentry, NULL);
+       d_move(sd->s_dentry, new_dentry);
+
+       mutex_lock(&sysfs_mutex);
+
+       sysfs_unlink_sibling(sd);
+       sysfs_get(new_parent_sd);
+       sysfs_put(sd->s_parent);
+       sd->s_parent = new_parent_sd;
+       sysfs_link_sibling(sd);
+
+       mutex_unlock(&sysfs_mutex);
+
+       error = 0;
+       goto out_unlock;
+
+ out_drop:
+       d_drop(new_dentry);
+ out_unlock:
+       mutex_unlock(&new_parent->d_inode->i_mutex);
+ out_dput:
+       kfree(dup_name);
+       dput(new_parent);
+       dput(old_dentry);
+       dput(new_dentry);
        return error;
 }
 
-int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
+int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
 {
-       struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry;
-       struct sysfs_dirent *new_parent_sd, *sd;
+       struct sysfs_dirent *sd = kobj->sd;
+       struct sysfs_dirent *new_parent_sd;
+       struct dentry *old_parent, *new_parent = NULL;
+       struct dentry *old_dentry = NULL, *new_dentry = NULL;
        int error;
 
-       old_parent_dentry = kobj->parent ?
-               kobj->parent->dentry : sysfs_mount->mnt_sb->s_root;
-       new_parent_dentry = new_parent ?
-               new_parent->dentry : sysfs_mount->mnt_sb->s_root;
+       BUG_ON(!sd->s_parent);
+       new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root;
+
+       /* get dentries */
+       old_dentry = sysfs_get_dentry(sd);
+       if (IS_ERR(old_dentry)) {
+               error = PTR_ERR(old_dentry);
+               goto out_dput;
+       }
+       old_parent = sd->s_parent->s_dentry;
+
+       new_parent = sysfs_get_dentry(new_parent_sd);
+       if (IS_ERR(new_parent)) {
+               error = PTR_ERR(new_parent);
+               goto out_dput;
+       }
 
-       if (old_parent_dentry->d_inode == new_parent_dentry->d_inode)
-               return 0;       /* nothing to move */
+       if (old_parent->d_inode == new_parent->d_inode) {
+               error = 0;
+               goto out_dput;  /* nothing to move */
+       }
 again:
-       mutex_lock(&old_parent_dentry->d_inode->i_mutex);
-       if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) {
-               mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+       mutex_lock(&old_parent->d_inode->i_mutex);
+       if (!mutex_trylock(&new_parent->d_inode->i_mutex)) {
+               mutex_unlock(&old_parent->d_inode->i_mutex);
                goto again;
        }
 
-       new_parent_sd = new_parent_dentry->d_fsdata;
-       sd = kobj->dentry->d_fsdata;
-
-       new_dentry = lookup_one_len(kobj->name, new_parent_dentry,
-                                   strlen(kobj->name));
+       new_dentry = lookup_one_len(kobj->name, new_parent, strlen(kobj->name));
        if (IS_ERR(new_dentry)) {
                error = PTR_ERR(new_dentry);
-               goto out;
+               goto out_unlock;
        } else
                error = 0;
        d_add(new_dentry, NULL);
-       d_move(kobj->dentry, new_dentry);
+       d_move(sd->s_dentry, new_dentry);
        dput(new_dentry);
 
        /* Remove from old parent's list and insert into new parent's list. */
-       list_del_init(&sd->s_sibling);
-       list_add(&sd->s_sibling, &new_parent_sd->s_children);
+       mutex_lock(&sysfs_mutex);
+
+       sysfs_unlink_sibling(sd);
+       sysfs_get(new_parent_sd);
+       sysfs_put(sd->s_parent);
+       sd->s_parent = new_parent_sd;
+       sysfs_link_sibling(sd);
 
-out:
-       mutex_unlock(&new_parent_dentry->d_inode->i_mutex);
-       mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+       mutex_unlock(&sysfs_mutex);
 
+ out_unlock:
+       mutex_unlock(&new_parent->d_inode->i_mutex);
+       mutex_unlock(&old_parent->d_inode->i_mutex);
+ out_dput:
+       dput(new_parent);
+       dput(old_dentry);
+       dput(new_dentry);
        return error;
 }
 
@@ -496,23 +1042,27 @@ static int sysfs_dir_open(struct inode *inode, struct file *file)
 {
        struct dentry * dentry = file->f_path.dentry;
        struct sysfs_dirent * parent_sd = dentry->d_fsdata;
+       struct sysfs_dirent * sd;
 
-       mutex_lock(&dentry->d_inode->i_mutex);
-       file->private_data = sysfs_new_dirent(parent_sd, NULL);
-       mutex_unlock(&dentry->d_inode->i_mutex);
-
-       return file->private_data ? 0 : -ENOMEM;
+       sd = sysfs_new_dirent("_DIR_", 0, 0);
+       if (sd) {
+               mutex_lock(&sysfs_mutex);
+               sd->s_parent = sysfs_get(parent_sd);
+               sysfs_link_sibling(sd);
+               mutex_unlock(&sysfs_mutex);
+       }
 
+       file->private_data = sd;
+       return sd ? 0 : -ENOMEM;
 }
 
 static int sysfs_dir_close(struct inode *inode, struct file *file)
 {
-       struct dentry * dentry = file->f_path.dentry;
        struct sysfs_dirent * cursor = file->private_data;
 
-       mutex_lock(&dentry->d_inode->i_mutex);
-       list_del_init(&cursor->s_sibling);
-       mutex_unlock(&dentry->d_inode->i_mutex);
+       mutex_lock(&sysfs_mutex);
+       sysfs_unlink_sibling(cursor);
+       mutex_unlock(&sysfs_mutex);
 
        release_sysfs_dirent(cursor);
 
@@ -530,7 +1080,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
        struct dentry *dentry = filp->f_path.dentry;
        struct sysfs_dirent * parent_sd = dentry->d_fsdata;
        struct sysfs_dirent *cursor = filp->private_data;
-       struct list_head *p, *q = &cursor->s_sibling;
+       struct sysfs_dirent **pos;
        ino_t ino;
        int i = filp->f_pos;
 
@@ -543,38 +1093,52 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
                        i++;
                        /* fallthrough */
                case 1:
-                       ino = parent_ino(dentry);
+                       if (parent_sd->s_parent)
+                               ino = parent_sd->s_parent->s_ino;
+                       else
+                               ino = parent_sd->s_ino;
                        if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
                                break;
                        filp->f_pos++;
                        i++;
                        /* fallthrough */
                default:
+                       mutex_lock(&sysfs_mutex);
+
+                       pos = &parent_sd->s_children;
+                       while (*pos != cursor)
+                               pos = &(*pos)->s_sibling;
+
+                       /* unlink cursor */
+                       *pos = cursor->s_sibling;
+
                        if (filp->f_pos == 2)
-                               list_move(q, &parent_sd->s_children);
+                               pos = &parent_sd->s_children;
 
-                       for (p=q->next; p!= &parent_sd->s_children; p=p->next) {
-                               struct sysfs_dirent *next;
+                       for ( ; *pos; pos = &(*pos)->s_sibling) {
+                               struct sysfs_dirent *next = *pos;
                                const char * name;
                                int len;
 
-                               next = list_entry(p, struct sysfs_dirent,
-                                                  s_sibling);
-                               if (!next->s_element)
+                               if (!sysfs_type(next))
                                        continue;
 
-                               name = sysfs_get_name(next);
+                               name = next->s_name;
                                len = strlen(name);
                                ino = next->s_ino;
 
                                if (filldir(dirent, name, len, filp->f_pos, ino,
                                                 dt_type(next)) < 0)
-                                       return 0;
+                                       break;
 
-                               list_move(q, p);
-                               p = q;
                                filp->f_pos++;
                        }
+
+                       /* put cursor back in */
+                       cursor->s_sibling = *pos;
+                       *pos = cursor;
+
+                       mutex_unlock(&sysfs_mutex);
        }
        return 0;
 }
@@ -583,7 +1147,6 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
 {
        struct dentry * dentry = file->f_path.dentry;
 
-       mutex_lock(&dentry->d_inode->i_mutex);
        switch (origin) {
                case 1:
                        offset += file->f_pos;
@@ -591,31 +1154,35 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
                        if (offset >= 0)
                                break;
                default:
-                       mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
                        return -EINVAL;
        }
        if (offset != file->f_pos) {
+               mutex_lock(&sysfs_mutex);
+
                file->f_pos = offset;
                if (file->f_pos >= 2) {
                        struct sysfs_dirent *sd = dentry->d_fsdata;
                        struct sysfs_dirent *cursor = file->private_data;
-                       struct list_head *p;
+                       struct sysfs_dirent **pos;
                        loff_t n = file->f_pos - 2;
 
-                       list_del(&cursor->s_sibling);
-                       p = sd->s_children.next;
-                       while (n && p != &sd->s_children) {
-                               struct sysfs_dirent *next;
-                               next = list_entry(p, struct sysfs_dirent,
-                                                  s_sibling);
-                               if (next->s_element)
+                       sysfs_unlink_sibling(cursor);
+
+                       pos = &sd->s_children;
+                       while (n && *pos) {
+                               struct sysfs_dirent *next = *pos;
+                               if (sysfs_type(next))
                                        n--;
-                               p = p->next;
+                               pos = &(*pos)->s_sibling;
                        }
-                       list_add_tail(&cursor->s_sibling, p);
+
+                       cursor->s_sibling = *pos;
+                       *pos = cursor;
                }
+
+               mutex_unlock(&sysfs_mutex);
        }
-       mutex_unlock(&dentry->d_inode->i_mutex);
+
        return offset;
 }
 
@@ -628,12 +1195,20 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
 int sysfs_make_shadowed_dir(struct kobject *kobj,
        void * (*follow_link)(struct dentry *, struct nameidata *))
 {
+       struct dentry *dentry;
        struct inode *inode;
        struct inode_operations *i_op;
 
-       inode = kobj->dentry->d_inode;
-       if (inode->i_op != &sysfs_dir_inode_operations)
+       /* get dentry for @kobj->sd, dentry of a shadowed dir is pinned */
+       dentry = sysfs_get_dentry(kobj->sd);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
+
+       inode = dentry->d_inode;
+       if (inode->i_op != &sysfs_dir_inode_operations) {
+               dput(dentry);
                return -EINVAL;
+       }
 
        i_op = kmalloc(sizeof(*i_op), GFP_KERNEL);
        if (!i_op)
@@ -658,54 +1233,72 @@ int sysfs_make_shadowed_dir(struct kobject *kobj,
  *     directory.
  */
 
-struct dentry *sysfs_create_shadow_dir(struct kobject *kobj)
+struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj)
 {
-       struct sysfs_dirent *sd;
-       struct dentry *parent, *dir, *shadow;
+       struct sysfs_dirent *parent_sd = kobj->sd->s_parent;
+       struct dentry *dir, *parent, *shadow;
        struct inode *inode;
+       struct sysfs_dirent *sd;
+       struct sysfs_addrm_cxt acxt;
 
-       dir = kobj->dentry;
-       inode = dir->d_inode;
+       dir = sysfs_get_dentry(kobj->sd);
+       if (IS_ERR(dir)) {
+               sd = (void *)dir;
+               goto out;
+       }
        parent = dir->d_parent;
-       shadow = ERR_PTR(-EINVAL);
+
+       inode = dir->d_inode;
+       sd = ERR_PTR(-EINVAL);
        if (!sysfs_is_shadowed_inode(inode))
-               goto out;
+               goto out_dput;
 
        shadow = d_alloc(parent, &dir->d_name);
        if (!shadow)
                goto nomem;
 
-       sd = __sysfs_make_dirent(shadow, kobj, inode->i_mode, SYSFS_DIR);
+       sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR);
        if (!sd)
                goto nomem;
+       sd->s_elem.dir.kobj = kobj;
 
+       sysfs_addrm_start(&acxt, parent_sd);
+
+       /* add but don't link into children list */
+       sysfs_add_one(&acxt, sd);
+
+       /* attach and instantiate dentry */
+       sysfs_attach_dentry(sd, shadow);
        d_instantiate(shadow, igrab(inode));
-       inc_nlink(inode);
-       inc_nlink(parent->d_inode);
-       shadow->d_op = &sysfs_dentry_ops;
+       inc_nlink(inode);       /* tj: synchronization? */
+
+       sysfs_addrm_finish(&acxt);
 
        dget(shadow);           /* Extra count - pin the dentry in core */
 
-out:
-       return shadow;
-nomem:
+       goto out_dput;
+
+ nomem:
        dput(shadow);
-       shadow = ERR_PTR(-ENOMEM);
-       goto out;
+       sd = ERR_PTR(-ENOMEM);
+ out_dput:
+       dput(dir);
+ out:
+       return sd;
 }
 
 /**
  *     sysfs_remove_shadow_dir - remove an object's directory.
- *     @shadow: dentry of shadow directory
+ *     @shadow_sd: sysfs_dirent of shadow directory
  *
  *     The only thing special about this is that we remove any files in
  *     the directory before we remove the directory, and we've inlined
  *     what used to be sysfs_rmdir() below, instead of calling separately.
  */
 
-void sysfs_remove_shadow_dir(struct dentry *shadow)
+void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd)
 {
-       __sysfs_remove_dir(shadow);
+       __sysfs_remove_dir(shadow_sd);
 }
 
 const struct file_operations sysfs_dir_operations = {
index b502c7197ec063777d90af4c49f038e95acd0c9e..cc497994b2a83dd91931d8d8b2f67bcc30aea80c 100644 (file)
@@ -50,29 +50,15 @@ static struct sysfs_ops subsys_sysfs_ops = {
        .store  = subsys_attr_store,
 };
 
-/**
- *     add_to_collection - add buffer to a collection
- *     @buffer:        buffer to be added
- *     @node:          inode of set to add to
- */
-
-static inline void
-add_to_collection(struct sysfs_buffer *buffer, struct inode *node)
-{
-       struct sysfs_buffer_collection *set = node->i_private;
-
-       mutex_lock(&node->i_mutex);
-       list_add(&buffer->associates, &set->associates);
-       mutex_unlock(&node->i_mutex);
-}
-
-static inline void
-remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
-{
-       mutex_lock(&node->i_mutex);
-       list_del(&buffer->associates);
-       mutex_unlock(&node->i_mutex);
-}
+struct sysfs_buffer {
+       size_t                  count;
+       loff_t                  pos;
+       char                    * page;
+       struct sysfs_ops        * ops;
+       struct semaphore        sem;
+       int                     needs_read_fill;
+       int                     event;
+};
 
 /**
  *     fill_read_buffer - allocate and fill buffer from object.
@@ -87,9 +73,8 @@ remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
  */
 static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
 {
-       struct sysfs_dirent * sd = dentry->d_fsdata;
-       struct attribute * attr = to_attr(dentry);
-       struct kobject * kobj = to_kobj(dentry->d_parent);
+       struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+       struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
        struct sysfs_ops * ops = buffer->ops;
        int ret = 0;
        ssize_t count;
@@ -99,8 +84,15 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
        if (!buffer->page)
                return -ENOMEM;
 
-       buffer->event = atomic_read(&sd->s_event);
-       count = ops->show(kobj,attr,buffer->page);
+       /* need attr_sd for attr and ops, its parent for kobj */
+       if (!sysfs_get_active_two(attr_sd))
+               return -ENODEV;
+
+       buffer->event = atomic_read(&attr_sd->s_event);
+       count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page);
+
+       sysfs_put_active_two(attr_sd);
+
        BUG_ON(count > (ssize_t)PAGE_SIZE);
        if (count >= 0) {
                buffer->needs_read_fill = 0;
@@ -138,10 +130,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 
        down(&buffer->sem);
        if (buffer->needs_read_fill) {
-               if (buffer->orphaned)
-                       retval = -ENODEV;
-               else
-                       retval = fill_read_buffer(file->f_path.dentry,buffer);
+               retval = fill_read_buffer(file->f_path.dentry,buffer);
                if (retval)
                        goto out;
        }
@@ -196,14 +185,23 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
  *     passing the buffer that we acquired in fill_write_buffer().
  */
 
-static int 
+static int
 flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
 {
-       struct attribute * attr = to_attr(dentry);
-       struct kobject * kobj = to_kobj(dentry->d_parent);
+       struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+       struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
        struct sysfs_ops * ops = buffer->ops;
+       int rc;
+
+       /* need attr_sd for attr and ops, its parent for kobj */
+       if (!sysfs_get_active_two(attr_sd))
+               return -ENODEV;
+
+       rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count);
 
-       return ops->store(kobj,attr,buffer->page,count);
+       sysfs_put_active_two(attr_sd);
+
+       return rc;
 }
 
 
@@ -231,37 +229,26 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
        ssize_t len;
 
        down(&buffer->sem);
-       if (buffer->orphaned) {
-               len = -ENODEV;
-               goto out;
-       }
        len = fill_write_buffer(buffer, buf, count);
        if (len > 0)
                len = flush_write_buffer(file->f_path.dentry, buffer, len);
        if (len > 0)
                *ppos += len;
-out:
        up(&buffer->sem);
        return len;
 }
 
 static int sysfs_open_file(struct inode *inode, struct file *file)
 {
-       struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
-       struct attribute * attr = to_attr(file->f_path.dentry);
-       struct sysfs_buffer_collection *set;
+       struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+       struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
        struct sysfs_buffer * buffer;
        struct sysfs_ops * ops = NULL;
-       int error = 0;
-
-       if (!kobj || !attr)
-               goto Einval;
+       int error;
 
-       /* Grab the module reference for this attribute if we have one */
-       if (!try_module_get(attr->owner)) {
-               error = -ENODEV;
-               goto Done;
-       }
+       /* need attr_sd for attr and ops, its parent for kobj */
+       if (!sysfs_get_active_two(attr_sd))
+               return -ENODEV;
 
        /* if the kobject has no ktype, then we assume that it is a subsystem
         * itself, and use ops for it.
@@ -273,33 +260,21 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
        else
                ops = &subsys_sysfs_ops;
 
+       error = -EACCES;
+
        /* No sysfs operations, either from having no subsystem,
         * or the subsystem have no operations.
         */
        if (!ops)
-               goto Eaccess;
-
-       /* make sure we have a collection to add our buffers to */
-       mutex_lock(&inode->i_mutex);
-       if (!(set = inode->i_private)) {
-               if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) {
-                       error = -ENOMEM;
-                       goto Done;
-               } else {
-                       INIT_LIST_HEAD(&set->associates);
-               }
-       }
-       mutex_unlock(&inode->i_mutex);
+               goto err_out;
 
        /* File needs write support.
         * The inode's perms must say it's ok, 
         * and we must have a store method.
         */
        if (file->f_mode & FMODE_WRITE) {
-
                if (!(inode->i_mode & S_IWUGO) || !ops->store)
-                       goto Eaccess;
-
+                       goto err_out;
        }
 
        /* File needs read support.
@@ -308,48 +283,38 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
         */
        if (file->f_mode & FMODE_READ) {
                if (!(inode->i_mode & S_IRUGO) || !ops->show)
-                       goto Eaccess;
+                       goto err_out;
        }
 
        /* No error? Great, allocate a buffer for the file, and store it
         * it in file->private_data for easy access.
         */
+       error = -ENOMEM;
        buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
-       if (buffer) {
-               INIT_LIST_HEAD(&buffer->associates);
-               init_MUTEX(&buffer->sem);
-               buffer->needs_read_fill = 1;
-               buffer->ops = ops;
-               add_to_collection(buffer, inode);
-               file->private_data = buffer;
-       } else
-               error = -ENOMEM;
-       goto Done;
-
- Einval:
-       error = -EINVAL;
-       goto Done;
- Eaccess:
-       error = -EACCES;
-       module_put(attr->owner);
- Done:
-       if (error)
-               kobject_put(kobj);
+       if (!buffer)
+               goto err_out;
+
+       init_MUTEX(&buffer->sem);
+       buffer->needs_read_fill = 1;
+       buffer->ops = ops;
+       file->private_data = buffer;
+
+       /* open succeeded, put active references and pin attr_sd */
+       sysfs_put_active_two(attr_sd);
+       sysfs_get(attr_sd);
+       return 0;
+
+ err_out:
+       sysfs_put_active_two(attr_sd);
        return error;
 }
 
 static int sysfs_release(struct inode * inode, struct file * filp)
 {
-       struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
-       struct attribute * attr = to_attr(filp->f_path.dentry);
-       struct module * owner = attr->owner;
-       struct sysfs_buffer * buffer = filp->private_data;
+       struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
+       struct sysfs_buffer *buffer = filp->private_data;
 
-       if (buffer)
-               remove_from_collection(buffer, inode);
-       kobject_put(kobj);
-       /* After this point, attr should not be accessed. */
-       module_put(owner);
+       sysfs_put(attr_sd);
 
        if (buffer) {
                if (buffer->page)
@@ -376,57 +341,43 @@ static int sysfs_release(struct inode * inode, struct file * filp)
 static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
 {
        struct sysfs_buffer * buffer = filp->private_data;
-       struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
-       struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata;
-       int res = 0;
+       struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
+       struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+
+       /* need parent for the kobj, grab both */
+       if (!sysfs_get_active_two(attr_sd))
+               goto trigger;
 
        poll_wait(filp, &kobj->poll, wait);
 
-       if (buffer->event != atomic_read(&sd->s_event)) {
-               res = POLLERR|POLLPRI;
-               buffer->needs_read_fill = 1;
-       }
+       sysfs_put_active_two(attr_sd);
 
-       return res;
-}
+       if (buffer->event != atomic_read(&attr_sd->s_event))
+               goto trigger;
 
+       return 0;
 
-static struct dentry *step_down(struct dentry *dir, const char * name)
-{
-       struct dentry * de;
-
-       if (dir == NULL || dir->d_inode == NULL)
-               return NULL;
-
-       mutex_lock(&dir->d_inode->i_mutex);
-       de = lookup_one_len(name, dir, strlen(name));
-       mutex_unlock(&dir->d_inode->i_mutex);
-       dput(dir);
-       if (IS_ERR(de))
-               return NULL;
-       if (de->d_inode == NULL) {
-               dput(de);
-               return NULL;
-       }
-       return de;
+ trigger:
+       buffer->needs_read_fill = 1;
+       return POLLERR|POLLPRI;
 }
 
-void sysfs_notify(struct kobject * k, char *dir, char *attr)
+void sysfs_notify(struct kobject *k, char *dir, char *attr)
 {
-       struct dentry *de = k->dentry;
-       if (de)
-               dget(de);
-       if (de && dir)
-               de = step_down(de, dir);
-       if (de && attr)
-               de = step_down(de, attr);
-       if (de) {
-               struct sysfs_dirent * sd = de->d_fsdata;
-               if (sd)
-                       atomic_inc(&sd->s_event);
+       struct sysfs_dirent *sd = k->sd;
+
+       mutex_lock(&sysfs_mutex);
+
+       if (sd && dir)
+               sd = sysfs_find_dirent(sd, dir);
+       if (sd && attr)
+               sd = sysfs_find_dirent(sd, attr);
+       if (sd) {
+               atomic_inc(&sd->s_event);
                wake_up_interruptible(&k->poll);
-               dput(de);
        }
+
+       mutex_unlock(&sysfs_mutex);
 }
 EXPORT_SYMBOL_GPL(sysfs_notify);
 
@@ -440,19 +391,30 @@ const struct file_operations sysfs_file_operations = {
 };
 
 
-int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
+int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
+                  int type)
 {
-       struct sysfs_dirent * parent_sd = dir->d_fsdata;
        umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
-       int error = -EEXIST;
+       struct sysfs_addrm_cxt acxt;
+       struct sysfs_dirent *sd;
 
-       mutex_lock(&dir->d_inode->i_mutex);
-       if (!sysfs_dirent_exist(parent_sd, attr->name))
-               error = sysfs_make_dirent(parent_sd, NULL, (void *)attr,
-                                         mode, type);
-       mutex_unlock(&dir->d_inode->i_mutex);
+       sd = sysfs_new_dirent(attr->name, mode, type);
+       if (!sd)
+               return -ENOMEM;
+       sd->s_elem.attr.attr = (void *)attr;
 
-       return error;
+       sysfs_addrm_start(&acxt, dir_sd);
+
+       if (!sysfs_find_dirent(dir_sd, attr->name)) {
+               sysfs_add_one(&acxt, sd);
+               sysfs_link_sibling(sd);
+       }
+
+       if (sysfs_addrm_finish(&acxt))
+               return 0;
+
+       sysfs_put(sd);
+       return -EEXIST;
 }
 
 
@@ -464,9 +426,9 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
 
 int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
 {
-       BUG_ON(!kobj || !kobj->dentry || !attr);
+       BUG_ON(!kobj || !kobj->sd || !attr);
 
-       return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR);
+       return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
 
 }
 
@@ -480,16 +442,16 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
 int sysfs_add_file_to_group(struct kobject *kobj,
                const struct attribute *attr, const char *group)
 {
-       struct dentry *dir;
+       struct sysfs_dirent *dir_sd;
        int error;
 
-       dir = lookup_one_len(group, kobj->dentry, strlen(group));
-       if (IS_ERR(dir))
-               error = PTR_ERR(dir);
-       else {
-               error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR);
-               dput(dir);
-       }
+       dir_sd = sysfs_get_dirent(kobj->sd, group);
+       if (!dir_sd)
+               return -ENOENT;
+
+       error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR);
+       sysfs_put(dir_sd);
+
        return error;
 }
 EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
@@ -502,30 +464,31 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
  */
 int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
 {
-       struct dentry * dir = kobj->dentry;
-       struct dentry * victim;
-       int res = -ENOENT;
-
-       mutex_lock(&dir->d_inode->i_mutex);
-       victim = lookup_one_len(attr->name, dir, strlen(attr->name));
-       if (!IS_ERR(victim)) {
-               /* make sure dentry is really there */
-               if (victim->d_inode && 
-                   (victim->d_parent->d_inode == dir->d_inode)) {
-                       victim->d_inode->i_mtime = CURRENT_TIME;
-                       fsnotify_modify(victim);
-                       res = 0;
-               } else
-                       d_drop(victim);
-               
-               /**
-                * Drop the reference acquired from lookup_one_len() above.
-                */
-               dput(victim);
+       struct sysfs_dirent *victim_sd = NULL;
+       struct dentry *victim = NULL;
+       int rc;
+
+       rc = -ENOENT;
+       victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
+       if (!victim_sd)
+               goto out;
+
+       victim = sysfs_get_dentry(victim_sd);
+       if (IS_ERR(victim)) {
+               rc = PTR_ERR(victim);
+               victim = NULL;
+               goto out;
        }
-       mutex_unlock(&dir->d_inode->i_mutex);
 
-       return res;
+       mutex_lock(&victim->d_inode->i_mutex);
+       victim->d_inode->i_mtime = CURRENT_TIME;
+       fsnotify_modify(victim);
+       mutex_unlock(&victim->d_inode->i_mutex);
+       rc = 0;
+ out:
+       dput(victim);
+       sysfs_put(victim_sd);
+       return rc;
 }
 
 
@@ -538,30 +501,34 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
  */
 int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
 {
-       struct dentry *dir = kobj->dentry;
-       struct dentry *victim;
+       struct sysfs_dirent *victim_sd = NULL;
+       struct dentry *victim = NULL;
        struct inode * inode;
        struct iattr newattrs;
-       int res = -ENOENT;
-
-       mutex_lock(&dir->d_inode->i_mutex);
-       victim = lookup_one_len(attr->name, dir, strlen(attr->name));
-       if (!IS_ERR(victim)) {
-               if (victim->d_inode &&
-                   (victim->d_parent->d_inode == dir->d_inode)) {
-                       inode = victim->d_inode;
-                       mutex_lock(&inode->i_mutex);
-                       newattrs.ia_mode = (mode & S_IALLUGO) |
-                                               (inode->i_mode & ~S_IALLUGO);
-                       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-                       res = notify_change(victim, &newattrs);
-                       mutex_unlock(&inode->i_mutex);
-               }
-               dput(victim);
+       int rc;
+
+       rc = -ENOENT;
+       victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
+       if (!victim_sd)
+               goto out;
+
+       victim = sysfs_get_dentry(victim_sd);
+       if (IS_ERR(victim)) {
+               rc = PTR_ERR(victim);
+               victim = NULL;
+               goto out;
        }
-       mutex_unlock(&dir->d_inode->i_mutex);
 
-       return res;
+       inode = victim->d_inode;
+       mutex_lock(&inode->i_mutex);
+       newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+       rc = notify_change(victim, &newattrs);
+       mutex_unlock(&inode->i_mutex);
+ out:
+       dput(victim);
+       sysfs_put(victim_sd);
+       return rc;
 }
 EXPORT_SYMBOL_GPL(sysfs_chmod_file);
 
@@ -576,7 +543,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file);
 
 void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
 {
-       sysfs_hash_and_remove(kobj->dentry, attr->name);
+       sysfs_hash_and_remove(kobj->sd, attr->name);
 }
 
 
@@ -589,12 +556,12 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
 void sysfs_remove_file_from_group(struct kobject *kobj,
                const struct attribute *attr, const char *group)
 {
-       struct dentry *dir;
+       struct sysfs_dirent *dir_sd;
 
-       dir = lookup_one_len(group, kobj->dentry, strlen(group));
-       if (!IS_ERR(dir)) {
-               sysfs_hash_and_remove(dir, attr->name);
-               dput(dir);
+       dir_sd = sysfs_get_dirent(kobj->sd, group);
+       if (dir_sd) {
+               sysfs_hash_and_remove(dir_sd, attr->name);
+               sysfs_put(dir_sd);
        }
 }
 EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
index 52eed2a7a5efbf91061362b11ca54794d22e0c25..f318b73c790c8d2b058bd68ac6646b2adb550802 100644 (file)
 #include "sysfs.h"
 
 
-static void remove_files(struct dentry * dir, 
-                        const struct attribute_group * grp)
+static void remove_files(struct sysfs_dirent *dir_sd,
+                        const struct attribute_group *grp)
 {
        struct attribute *const* attr;
 
        for (attr = grp->attrs; *attr; attr++)
-               sysfs_hash_and_remove(dir,(*attr)->name);
+               sysfs_hash_and_remove(dir_sd, (*attr)->name);
 }
 
-static int create_files(struct dentry * dir,
-                       const struct attribute_group * grp)
+static int create_files(struct sysfs_dirent *dir_sd,
+                       const struct attribute_group *grp)
 {
        struct attribute *const* attr;
        int error = 0;
 
-       for (attr = grp->attrs; *attr && !error; attr++) {
-               error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
-       }
+       for (attr = grp->attrs; *attr && !error; attr++)
+               error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
        if (error)
-               remove_files(dir,grp);
+               remove_files(dir_sd, grp);
        return error;
 }
 
@@ -45,44 +44,44 @@ static int create_files(struct dentry * dir,
 int sysfs_create_group(struct kobject * kobj, 
                       const struct attribute_group * grp)
 {
-       struct dentry * dir;
+       struct sysfs_dirent *sd;
        int error;
 
-       BUG_ON(!kobj || !kobj->dentry);
+       BUG_ON(!kobj || !kobj->sd);
 
        if (grp->name) {
-               error = sysfs_create_subdir(kobj,grp->name,&dir);
+               error = sysfs_create_subdir(kobj, grp->name, &sd);
                if (error)
                        return error;
        } else
-               dir = kobj->dentry;
-       dir = dget(dir);
-       if ((error = create_files(dir,grp))) {
+               sd = kobj->sd;
+       sysfs_get(sd);
+       error = create_files(sd, grp);
+       if (error) {
                if (grp->name)
-                       sysfs_remove_subdir(dir);
+                       sysfs_remove_subdir(sd);
        }
-       dput(dir);
+       sysfs_put(sd);
        return error;
 }
 
 void sysfs_remove_group(struct kobject * kobj, 
                        const struct attribute_group * grp)
 {
-       struct dentry * dir;
+       struct sysfs_dirent *dir_sd = kobj->sd;
+       struct sysfs_dirent *sd;
 
        if (grp->name) {
-               dir = lookup_one_len_kern(grp->name, kobj->dentry,
-                               strlen(grp->name));
-               BUG_ON(IS_ERR(dir));
-       }
-       else
-               dir = dget(kobj->dentry);
+               sd = sysfs_get_dirent(dir_sd, grp->name);
+               BUG_ON(!sd);
+       } else
+               sd = sysfs_get(dir_sd);
 
-       remove_files(dir,grp);
+       remove_files(sd, grp);
        if (grp->name)
-               sysfs_remove_subdir(dir);
-       /* release the ref. taken in this routine */
-       dput(dir);
+               sysfs_remove_subdir(sd);
+
+       sysfs_put(sd);
 }
 
 
index 5266eec15f6e35766c84939f1c7663690d6c3930..3756e152285ab0ea219c90a698f4391040f17940 100644 (file)
@@ -133,187 +133,94 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
  */
 static struct lock_class_key sysfs_inode_imutex_key;
 
-struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
+void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
 {
-       struct inode * inode = new_inode(sysfs_sb);
-       if (inode) {
-               inode->i_blocks = 0;
-               inode->i_mapping->a_ops = &sysfs_aops;
-               inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
-               inode->i_op = &sysfs_inode_operations;
-               inode->i_ino = sd->s_ino;
-               lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
-
-               if (sd->s_iattr) {
-                       /* sysfs_dirent has non-default attributes
-                        * get them for the new inode from persistent copy
-                        * in sysfs_dirent
-                        */
-                       set_inode_attr(inode, sd->s_iattr);
-               } else
-                       set_default_inode_attr(inode, mode);
-       }
-       return inode;
-}
-
-int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
-{
-       int error = 0;
-       struct inode * inode = NULL;
-       if (dentry) {
-               if (!dentry->d_inode) {
-                       struct sysfs_dirent * sd = dentry->d_fsdata;
-                       if ((inode = sysfs_new_inode(mode, sd))) {
-                               if (dentry->d_parent && dentry->d_parent->d_inode) {
-                                       struct inode *p_inode = dentry->d_parent->d_inode;
-                                       p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
-                               }
-                               goto Proceed;
-                       }
-                       else 
-                               error = -ENOMEM;
-               } else
-                       error = -EEXIST;
-       } else 
-               error = -ENOENT;
-       goto Done;
-
- Proceed:
-       if (init)
-               error = init(inode);
-       if (!error) {
-               d_instantiate(dentry, inode);
-               if (S_ISDIR(mode))
-                       dget(dentry);  /* pin only directory dentry in core */
+       inode->i_blocks = 0;
+       inode->i_mapping->a_ops = &sysfs_aops;
+       inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
+       inode->i_op = &sysfs_inode_operations;
+       inode->i_ino = sd->s_ino;
+       lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
+
+       if (sd->s_iattr) {
+               /* sysfs_dirent has non-default attributes
+                * get them for the new inode from persistent copy
+                * in sysfs_dirent
+                */
+               set_inode_attr(inode, sd->s_iattr);
        } else
-               iput(inode);
- Done:
-       return error;
+               set_default_inode_attr(inode, sd->s_mode);
 }
 
-/*
- * Get the name for corresponding element represented by the given sysfs_dirent
+/**
+ *     sysfs_get_inode - get inode for sysfs_dirent
+ *     @sd: sysfs_dirent to allocate inode for
+ *
+ *     Get inode for @sd.  If such inode doesn't exist, a new inode
+ *     is allocated and basics are initialized.  New inode is
+ *     returned locked.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     Pointer to allocated inode on success, NULL on failure.
  */
-const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
+struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
 {
-       struct attribute * attr;
-       struct bin_attribute * bin_attr;
-       struct sysfs_symlink  * sl;
-
-       BUG_ON(!sd || !sd->s_element);
-
-       switch (sd->s_type) {
-               case SYSFS_DIR:
-                       /* Always have a dentry so use that */
-                       return sd->s_dentry->d_name.name;
-
-               case SYSFS_KOBJ_ATTR:
-                       attr = sd->s_element;
-                       return attr->name;
-
-               case SYSFS_KOBJ_BIN_ATTR:
-                       bin_attr = sd->s_element;
-                       return bin_attr->attr.name;
+       struct inode *inode;
 
-               case SYSFS_KOBJ_LINK:
-                       sl = sd->s_element;
-                       return sl->link_name;
-       }
-       return NULL;
-}
+       inode = iget_locked(sysfs_sb, sd->s_ino);
+       if (inode && (inode->i_state & I_NEW))
+               sysfs_init_inode(sd, inode);
 
-static inline void orphan_all_buffers(struct inode *node)
-{
-       struct sysfs_buffer_collection *set;
-       struct sysfs_buffer *buf;
-
-       mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD);
-       set = node->i_private;
-       if (set) {
-               list_for_each_entry(buf, &set->associates, associates) {
-                       down(&buf->sem);
-                       buf->orphaned = 1;
-                       up(&buf->sem);
-               }
-       }
-       mutex_unlock(&node->i_mutex);
+       return inode;
 }
 
-
-/*
- * Unhashes the dentry corresponding to given sysfs_dirent
- * Called with parent inode's i_mutex held.
+/**
+ *     sysfs_instantiate - instantiate dentry
+ *     @dentry: dentry to be instantiated
+ *     @inode: inode associated with @sd
+ *
+ *     Unlock @inode if locked and instantiate @dentry with @inode.
+ *
+ *     LOCKING:
+ *     None.
  */
-void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
+void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
 {
-       struct dentry *dentry = NULL;
-       struct inode *inode;
+       BUG_ON(!dentry || dentry->d_inode);
 
-       /* We're not holding a reference to ->s_dentry dentry but the
-        * field will stay valid as long as sysfs_lock is held.
-        */
-       spin_lock(&sysfs_lock);
-       spin_lock(&dcache_lock);
-
-       /* dget dentry if it's still alive */
-       if (sd->s_dentry && sd->s_dentry->d_inode)
-               dentry = dget_locked(sd->s_dentry);
-
-       spin_unlock(&dcache_lock);
-       spin_unlock(&sysfs_lock);
-
-       /* drop dentry */
-       if (dentry) {
-               spin_lock(&dcache_lock);
-               spin_lock(&dentry->d_lock);
-               if (!d_unhashed(dentry) && dentry->d_inode) {
-                       inode = dentry->d_inode;
-                       spin_lock(&inode->i_lock);
-                       __iget(inode);
-                       spin_unlock(&inode->i_lock);
-                       dget_locked(dentry);
-                       __d_drop(dentry);
-                       spin_unlock(&dentry->d_lock);
-                       spin_unlock(&dcache_lock);
-                       simple_unlink(parent->d_inode, dentry);
-                       orphan_all_buffers(inode);
-                       iput(inode);
-               } else {
-                       spin_unlock(&dentry->d_lock);
-                       spin_unlock(&dcache_lock);
-               }
+       if (inode->i_state & I_NEW)
+               unlock_new_inode(inode);
 
-               dput(dentry);
-       }
+       d_instantiate(dentry, inode);
 }
 
-int sysfs_hash_and_remove(struct dentry * dir, const char * name)
+int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
 {
-       struct sysfs_dirent * sd;
-       struct sysfs_dirent * parent_sd;
-       int found = 0;
+       struct sysfs_addrm_cxt acxt;
+       struct sysfs_dirent **pos, *sd;
 
-       if (!dir)
+       if (!dir_sd)
                return -ENOENT;
 
-       if (dir->d_inode == NULL)
-               /* no inode means this hasn't been made visible yet */
-               return -ENOENT;
+       sysfs_addrm_start(&acxt, dir_sd);
+
+       for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) {
+               sd = *pos;
 
-       parent_sd = dir->d_fsdata;
-       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
-       list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
-               if (!sd->s_element)
+               if (!sysfs_type(sd))
                        continue;
-               if (!strcmp(sysfs_get_name(sd), name)) {
-                       list_del_init(&sd->s_sibling);
-                       sysfs_drop_dentry(sd, dir);
-                       sysfs_put(sd);
-                       found = 1;
+               if (!strcmp(sd->s_name, name)) {
+                       *pos = sd->s_sibling;
+                       sd->s_sibling = NULL;
+                       sysfs_remove_one(&acxt, sd);
                        break;
                }
        }
-       mutex_unlock(&dir->d_inode->i_mutex);
 
-       return found ? 0 : -ENOENT;
+       if (sysfs_addrm_finish(&acxt))
+               return 0;
+       return -ENOENT;
 }
index 00ab9125d398984efa12496fa3b48ff405f62bad..402cc356203c9ac89f3325f320be5f5c5026312f 100644 (file)
@@ -19,28 +19,18 @@ struct vfsmount *sysfs_mount;
 struct super_block * sysfs_sb = NULL;
 struct kmem_cache *sysfs_dir_cachep;
 
-static void sysfs_clear_inode(struct inode *inode);
-
 static const struct super_operations sysfs_ops = {
        .statfs         = simple_statfs,
        .drop_inode     = sysfs_delete_inode,
-       .clear_inode    = sysfs_clear_inode,
 };
 
-static struct sysfs_dirent sysfs_root = {
-       .s_sibling      = LIST_HEAD_INIT(sysfs_root.s_sibling),
-       .s_children     = LIST_HEAD_INIT(sysfs_root.s_children),
-       .s_element      = NULL,
-       .s_type         = SYSFS_ROOT,
-       .s_iattr        = NULL,
+struct sysfs_dirent sysfs_root = {
+       .s_count        = ATOMIC_INIT(1),
+       .s_flags        = SYSFS_ROOT,
+       .s_mode         = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
        .s_ino          = 1,
 };
 
-static void sysfs_clear_inode(struct inode *inode)
-{
-       kfree(inode->i_private);
-}
-
 static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct inode *inode;
@@ -53,24 +43,26 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_time_gran = 1;
        sysfs_sb = sb;
 
-       inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
-                                &sysfs_root);
-       if (inode) {
-               inode->i_op = &sysfs_dir_inode_operations;
-               inode->i_fop = &sysfs_dir_operations;
-               /* directory inodes start off with i_nlink == 2 (for "." entry) */
-               inc_nlink(inode);
-       } else {
+       inode = new_inode(sysfs_sb);
+       if (!inode) {
                pr_debug("sysfs: could not get root inode\n");
                return -ENOMEM;
        }
 
+       sysfs_init_inode(&sysfs_root, inode);
+
+       inode->i_op = &sysfs_dir_inode_operations;
+       inode->i_fop = &sysfs_dir_operations;
+       /* directory inodes start off with i_nlink == 2 (for "." entry) */
+       inc_nlink(inode);
+
        root = d_alloc_root(inode);
        if (!root) {
                pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
                iput(inode);
                return -ENOMEM;
        }
+       sysfs_root.s_dentry = root;
        root->d_fsdata = &sysfs_root;
        sb->s_root = root;
        return 0;
index 7b9c5bfde920fb1ea30af8f81d4313f84bf981ec..2f86e04222907b2c19aab03adf6d2f2cabe092d1 100644 (file)
 
 #include "sysfs.h"
 
-static int object_depth(struct kobject * kobj)
+static int object_depth(struct sysfs_dirent *sd)
 {
-       struct kobject * p = kobj;
        int depth = 0;
-       do { depth++; } while ((p = p->parent));
+
+       for (; sd->s_parent; sd = sd->s_parent)
+               depth++;
+
        return depth;
 }
 
-static int object_path_length(struct kobject * kobj)
+static int object_path_length(struct sysfs_dirent * sd)
 {
-       struct kobject * p = kobj;
        int length = 1;
-       do {
-               length += strlen(kobject_name(p)) + 1;
-               p = p->parent;
-       } while (p);
+
+       for (; sd->s_parent; sd = sd->s_parent)
+               length += strlen(sd->s_name) + 1;
+
        return length;
 }
 
-static void fill_object_path(struct kobject * kobj, char * buffer, int length)
+static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length)
 {
-       struct kobject * p;
-
        --length;
-       for (p = kobj; p; p = p->parent) {
-               int cur = strlen(kobject_name(p));
+       for (; sd->s_parent; sd = sd->s_parent) {
+               int cur = strlen(sd->s_name);
 
                /* back up enough to print this bus id with '/' */
                length -= cur;
-               strncpy(buffer + length,kobject_name(p),cur);
+               strncpy(buffer + length, sd->s_name, cur);
                *(buffer + --length) = '/';
        }
 }
 
-static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target)
-{
-       struct sysfs_dirent * parent_sd = parent->d_fsdata;
-       struct sysfs_symlink * sl;
-       int error = 0;
-
-       error = -ENOMEM;
-       sl = kmalloc(sizeof(*sl), GFP_KERNEL);
-       if (!sl)
-               goto exit1;
-
-       sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
-       if (!sl->link_name)
-               goto exit2;
-
-       strcpy(sl->link_name, name);
-       sl->target_kobj = kobject_get(target);
-
-       error = sysfs_make_dirent(parent_sd, NULL, sl, S_IFLNK|S_IRWXUGO,
-                               SYSFS_KOBJ_LINK);
-       if (!error)
-               return 0;
-
-       kobject_put(target);
-       kfree(sl->link_name);
-exit2:
-       kfree(sl);
-exit1:
-       return error;
-}
-
 /**
  *     sysfs_create_link - create symlink between two objects.
  *     @kobj:  object whose directory we're creating the link in.
@@ -84,24 +52,57 @@ exit1:
  */
 int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
 {
-       struct dentry *dentry = NULL;
-       int error = -EEXIST;
+       struct sysfs_dirent *parent_sd = NULL;
+       struct sysfs_dirent *target_sd = NULL;
+       struct sysfs_dirent *sd = NULL;
+       struct sysfs_addrm_cxt acxt;
+       int error;
 
        BUG_ON(!name);
 
        if (!kobj) {
                if (sysfs_mount && sysfs_mount->mnt_sb)
-                       dentry = sysfs_mount->mnt_sb->s_root;
+                       parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
        } else
-               dentry = kobj->dentry;
+               parent_sd = kobj->sd;
+
+       error = -EFAULT;
+       if (!parent_sd)
+               goto out_put;
+
+       /* target->sd can go away beneath us but is protected with
+        * sysfs_assoc_lock.  Fetch target_sd from it.
+        */
+       spin_lock(&sysfs_assoc_lock);
+       if (target->sd)
+               target_sd = sysfs_get(target->sd);
+       spin_unlock(&sysfs_assoc_lock);
+
+       error = -ENOENT;
+       if (!target_sd)
+               goto out_put;
+
+       error = -ENOMEM;
+       sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
+       if (!sd)
+               goto out_put;
+       sd->s_elem.symlink.target_sd = target_sd;
 
-       if (!dentry)
-               return -EFAULT;
+       sysfs_addrm_start(&acxt, parent_sd);
 
-       mutex_lock(&dentry->d_inode->i_mutex);
-       if (!sysfs_dirent_exist(dentry->d_fsdata, name))
-               error = sysfs_add_link(dentry, name, target);
-       mutex_unlock(&dentry->d_inode->i_mutex);
+       if (!sysfs_find_dirent(parent_sd, name)) {
+               sysfs_add_one(&acxt, sd);
+               sysfs_link_sibling(sd);
+       }
+
+       if (sysfs_addrm_finish(&acxt))
+               return 0;
+
+       error = -EEXIST;
+       /* fall through */
+ out_put:
+       sysfs_put(target_sd);
+       sysfs_put(sd);
        return error;
 }
 
@@ -114,17 +115,17 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
 
 void sysfs_remove_link(struct kobject * kobj, const char * name)
 {
-       sysfs_hash_and_remove(kobj->dentry,name);
+       sysfs_hash_and_remove(kobj->sd, name);
 }
 
-static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
-                                char *path)
+static int sysfs_get_target_path(struct sysfs_dirent * parent_sd,
+                                struct sysfs_dirent * target_sd, char *path)
 {
        char * s;
        int depth, size;
 
-       depth = object_depth(kobj);
-       size = object_path_length(target) + depth * 3 - 1;
+       depth = object_depth(parent_sd);
+       size = object_path_length(target_sd) + depth * 3 - 1;
        if (size > PATH_MAX)
                return -ENAMETOOLONG;
 
@@ -133,7 +134,7 @@ static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
        for (s = path; depth--; s += 3)
                strcpy(s,"../");
 
-       fill_object_path(target, path, size);
+       fill_object_path(target_sd, path, size);
        pr_debug("%s: path = '%s'\n", __FUNCTION__, path);
 
        return 0;
@@ -141,27 +142,16 @@ static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
 
 static int sysfs_getlink(struct dentry *dentry, char * path)
 {
-       struct kobject *kobj, *target_kobj;
-       int error = 0;
+       struct sysfs_dirent *sd = dentry->d_fsdata;
+       struct sysfs_dirent *parent_sd = sd->s_parent;
+       struct sysfs_dirent *target_sd = sd->s_elem.symlink.target_sd;
+       int error;
 
-       kobj = sysfs_get_kobject(dentry->d_parent);
-       if (!kobj)
-               return -EINVAL;
+       mutex_lock(&sysfs_mutex);
+       error = sysfs_get_target_path(parent_sd, target_sd, path);
+       mutex_unlock(&sysfs_mutex);
 
-       target_kobj = sysfs_get_kobject(dentry);
-       if (!target_kobj) {
-               kobject_put(kobj);
-               return -EINVAL;
-       }
-
-       down_read(&sysfs_rename_sem);
-       error = sysfs_get_target_path(kobj, target_kobj, path);
-       up_read(&sysfs_rename_sem);
-       
-       kobject_put(kobj);
-       kobject_put(target_kobj);
        return error;
-
 }
 
 static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
index 502c949c402d9dd3de49ac922d9f1e1db2543e2a..6a37f2386a8d6621eb5dcff2de9e5e986b99e167 100644 (file)
@@ -1,9 +1,40 @@
+struct sysfs_elem_dir {
+       struct kobject          * kobj;
+};
+
+struct sysfs_elem_symlink {
+       struct sysfs_dirent     * target_sd;
+};
+
+struct sysfs_elem_attr {
+       struct attribute        * attr;
+};
+
+struct sysfs_elem_bin_attr {
+       struct bin_attribute    * bin_attr;
+};
+
+/*
+ * As long as s_count reference is held, the sysfs_dirent itself is
+ * accessible.  Dereferencing s_elem or any other outer entity
+ * requires s_active reference.
+ */
 struct sysfs_dirent {
        atomic_t                s_count;
-       struct list_head        s_sibling;
-       struct list_head        s_children;
-       void                    * s_element;
-       int                     s_type;
+       atomic_t                s_active;
+       struct sysfs_dirent     * s_parent;
+       struct sysfs_dirent     * s_sibling;
+       struct sysfs_dirent     * s_children;
+       const char              * s_name;
+
+       union {
+               struct sysfs_elem_dir           dir;
+               struct sysfs_elem_symlink       symlink;
+               struct sysfs_elem_attr          attr;
+               struct sysfs_elem_bin_attr      bin_attr;
+       }                       s_elem;
+
+       unsigned int            s_flags;
        umode_t                 s_mode;
        ino_t                   s_ino;
        struct dentry           * s_dentry;
@@ -11,30 +42,60 @@ struct sysfs_dirent {
        atomic_t                s_event;
 };
 
+#define SD_DEACTIVATED_BIAS    INT_MIN
+
+struct sysfs_addrm_cxt {
+       struct sysfs_dirent     *parent_sd;
+       struct inode            *parent_inode;
+       struct sysfs_dirent     *removed;
+       int                     cnt;
+};
+
 extern struct vfsmount * sysfs_mount;
+extern struct sysfs_dirent sysfs_root;
 extern struct kmem_cache *sysfs_dir_cachep;
 
-extern void sysfs_delete_inode(struct inode *inode);
-extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
-extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
+extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
+extern void sysfs_link_sibling(struct sysfs_dirent *sd);
+extern void sysfs_unlink_sibling(struct sysfs_dirent *sd);
+extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
+extern void sysfs_put_active(struct sysfs_dirent *sd);
+extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
+extern void sysfs_put_active_two(struct sysfs_dirent *sd);
+extern void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
+                             struct sysfs_dirent *parent_sd);
+extern void sysfs_add_one(struct sysfs_addrm_cxt *acxt,
+                         struct sysfs_dirent *sd);
+extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt,
+                            struct sysfs_dirent *sd);
+extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
 
-extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
-extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
-                               umode_t, int);
-
-extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
-extern int sysfs_hash_and_remove(struct dentry * dir, const char * name);
+extern void sysfs_delete_inode(struct inode *inode);
+extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode);
+extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd);
+extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode);
+
+extern void release_sysfs_dirent(struct sysfs_dirent * sd);
+extern struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
+                                             const unsigned char *name);
+extern struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+                                            const unsigned char *name);
+extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode,
+                                            int type);
+
+extern int sysfs_add_file(struct sysfs_dirent *dir_sd,
+                         const struct attribute *attr, int type);
+extern int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
 extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
 
-extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
-extern void sysfs_remove_subdir(struct dentry *);
+extern int sysfs_create_subdir(struct kobject *kobj, const char *name,
+                              struct sysfs_dirent **p_sd);
+extern void sysfs_remove_subdir(struct sysfs_dirent *sd);
 
-extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
-extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
 extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
 
-extern spinlock_t sysfs_lock;
-extern struct rw_semaphore sysfs_rename_sem;
+extern spinlock_t sysfs_assoc_lock;
+extern struct mutex sysfs_mutex;
 extern struct super_block * sysfs_sb;
 extern const struct file_operations sysfs_dir_operations;
 extern const struct file_operations sysfs_file_operations;
@@ -42,73 +103,9 @@ extern const struct file_operations bin_fops;
 extern const struct inode_operations sysfs_dir_inode_operations;
 extern const struct inode_operations sysfs_symlink_inode_operations;
 
-struct sysfs_symlink {
-       char * link_name;
-       struct kobject * target_kobj;
-};
-
-struct sysfs_buffer {
-       struct list_head                associates;
-       size_t                          count;
-       loff_t                          pos;
-       char                            * page;
-       struct sysfs_ops                * ops;
-       struct semaphore                sem;
-       int                             orphaned;
-       int                             needs_read_fill;
-       int                             event;
-};
-
-struct sysfs_buffer_collection {
-       struct list_head        associates;
-};
-
-static inline struct kobject * to_kobj(struct dentry * dentry)
-{
-       struct sysfs_dirent * sd = dentry->d_fsdata;
-       return ((struct kobject *) sd->s_element);
-}
-
-static inline struct attribute * to_attr(struct dentry * dentry)
+static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
 {
-       struct sysfs_dirent * sd = dentry->d_fsdata;
-       return ((struct attribute *) sd->s_element);
-}
-
-static inline struct bin_attribute * to_bin_attr(struct dentry * dentry)
-{
-       struct sysfs_dirent * sd = dentry->d_fsdata;
-       return ((struct bin_attribute *) sd->s_element);
-}
-
-static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
-{
-       struct kobject * kobj = NULL;
-
-       spin_lock(&dcache_lock);
-       if (!d_unhashed(dentry)) {
-               struct sysfs_dirent * sd = dentry->d_fsdata;
-               if (sd->s_type & SYSFS_KOBJ_LINK) {
-                       struct sysfs_symlink * sl = sd->s_element;
-                       kobj = kobject_get(sl->target_kobj);
-               } else
-                       kobj = kobject_get(sd->s_element);
-       }
-       spin_unlock(&dcache_lock);
-
-       return kobj;
-}
-
-static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
-{
-       if (sd->s_type & SYSFS_KOBJ_LINK) {
-               struct sysfs_symlink * sl = sd->s_element;
-               kfree(sl->link_name);
-               kobject_put(sl->target_kobj);
-               kfree(sl);
-       }
-       kfree(sd->s_iattr);
-       kmem_cache_free(sysfs_dir_cachep, sd);
+       return sd->s_flags & SYSFS_TYPE_MASK;
 }
 
 static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
@@ -122,7 +119,7 @@ static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
 
 static inline void sysfs_put(struct sysfs_dirent * sd)
 {
-       if (atomic_dec_and_test(&sd->s_count))
+       if (sd && atomic_dec_and_test(&sd->s_count))
                release_sysfs_dirent(sd);
 }
 
index 85aa1127c903f832282ba843e3a163de8563dbed..30ee7669b19f9622703478bd77c45aab598c628e 100644 (file)
@@ -199,30 +199,6 @@ pci_dma_sync_sg_for_device(struct pci_dev *dev, struct scatterlist *sg,
 
 extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
 
-/* True if the machine supports DAC addressing, and DEV can
-   make use of it given MASK.  */
-extern int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask);
-
-/* Convert to/from DAC dma address and struct page.  */
-extern dma64_addr_t pci_dac_page_to_dma(struct pci_dev *, struct page *,
-                                       unsigned long, int);
-extern struct page *pci_dac_dma_to_page(struct pci_dev *, dma64_addr_t);
-extern unsigned long pci_dac_dma_to_offset(struct pci_dev *, dma64_addr_t);
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr,
-                               size_t len, int direction)
-{
-       /* Nothing to do. */
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr,
-                                  size_t len, int direction)
-{
-       /* Nothing to do. */
-}
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
@@ -275,11 +251,6 @@ static inline int pci_proc_domain(struct pci_bus *bus)
        return hose->need_domain_info;
 }
 
-static inline void
-pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 struct pci_dev *alpha_gendev_to_pci(struct device *dev);
 
 #endif /* __KERNEL__ */
index c68e1680da0173d5754d1a1df4944120a5239e58..73237bd130a28b16f35709fa432c2457f8c0191c 100644 (file)
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+unifdef-y += hwcap.h
index b0369e176f7bbd95a3fa333498a77a43b5f136dc..8019ffd0ad3b61a23ee920a3b6b79e2009b16ec6 100644 (file)
@@ -16,6 +16,7 @@
 #ifndef AT91_DBGU_H
 #define AT91_DBGU_H
 
+#ifdef AT91_DBGU
 #define AT91_DBGU_CR           (AT91_DBGU + 0x00)      /* Control Register */
 #define AT91_DBGU_MR           (AT91_DBGU + 0x04)      /* Mode Register */
 #define AT91_DBGU_IER          (AT91_DBGU + 0x08)      /* Interrupt Enable Register */
 
 #define AT91_DBGU_CIDR         (AT91_DBGU + 0x40)      /* Chip ID Register */
 #define AT91_DBGU_EXID         (AT91_DBGU + 0x44)      /* Chip ID Extension Register */
+#define AT91_DBGU_FNR          (AT91_DBGU + 0x48)      /* Force NTRST Register [SAM9 only] */
+#define                AT91_DBGU_FNTRST        (1 << 0)                /* Force NTRST */
+
+#endif /* AT91_DBGU */
+
+/*
+ * Some AT91 parts that don't have full DEBUG units still support the ID
+ * and extensions register.
+ */
 #define                AT91_CIDR_VERSION       (0x1f << 0)             /* Version of the Device */
 #define                AT91_CIDR_EPROC         (7    << 5)             /* Embedded Processor */
 #define                AT91_CIDR_NVPSIZ        (0xf  << 8)             /* Nonvolatile Program Memory Size */
@@ -53,7 +63,4 @@
 #define                AT91_CIDR_NVPTYP        (7    << 28)            /* Nonvolatile Program Memory Type */
 #define                AT91_CIDR_EXT           (1    << 31)            /* Extension Flag */
 
-#define AT91_DBGU_FNR          (AT91_DBGU + 0x48)      /* Force NTRST Register [SAM9 only] */
-#define                AT91_DBGU_FNTRST        (1 << 0)                /* Force NTRST */
-
 #endif
diff --git a/include/asm-arm/arch-at91/at91x40.h b/include/asm-arm/arch-at91/at91x40.h
new file mode 100644 (file)
index 0000000..612203e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * include/asm-arm/arch-at91/at91x40.h
+ *
+ * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91X40_H
+#define AT91X40_H
+
+/*
+ *     IRQ list.
+ */
+#define AT91_ID_FIQ            0       /* FIQ */
+#define AT91_ID_SYS            1       /* System Peripheral */
+#define AT91X40_ID_USART0      2       /* USART port 0 */
+#define AT91X40_ID_USART1      3       /* USART port 1 */
+#define AT91X40_ID_TC0         4       /* Timer/Counter 0 */
+#define AT91X40_ID_TC1         5       /* Timer/Counter 1*/
+#define AT91X40_ID_TC2         6       /* Timer/Counter 2*/
+#define AT91X40_ID_WD          7       /* Watchdog? */
+#define AT91X40_ID_PIOA                8       /* Parallel IO Controller A */
+
+#define AT91X40_ID_IRQ0                16      /* External IRQ 0 */
+#define AT91X40_ID_IRQ1                17      /* External IRQ 1 */
+#define AT91X40_ID_IRQ2                18      /* External IRQ 2 */
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_BASE_SYS  0xffc00000
+
+#define AT91_EBI       (0xffe00000 - AT91_BASE_SYS)    /* External Bus Interface */
+#define AT91_SF                (0xfff00000 - AT91_BASE_SYS)    /* Special Function */
+#define AT91_USART1    (0xfffcc000 - AT91_BASE_SYS)    /* USART 1 */
+#define AT91_USART0    (0xfffd0000 - AT91_BASE_SYS)    /* USART 0 */
+#define AT91_TC                (0xfffe0000 - AT91_BASE_SYS)    /* Timer Counter */
+#define AT91_PIOA      (0xffff0000 - AT91_BASE_SYS)    /* PIO Controller A */
+#define AT91_PS                (0xffff4000 - AT91_BASE_SYS)    /* Power Save */
+#define AT91_WD                (0xffff8000 - AT91_BASE_SYS)    /* Watchdog Timer */
+#define AT91_AIC       (0xfffff000 - AT91_BASE_SYS)    /* Advanced Interrupt Controller */
+
+/*
+ * The AT91x40 series doesn't have a debug unit like the other AT91 parts.
+ * But it does have a chip identify register and extension ID, so define at
+ * least these here.
+ */
+#define AT91_DBGU_CIDR (AT91_SF + 0)   /* CIDR in PS segment */
+#define AT91_DBGU_EXID (AT91_SF + 4)   /* EXID in PS segment */
+
+#endif /* AT91X40_H */
index ef93c30a9c5fd17fd642c35be4c5f51c9ecdb98b..080cbb401a874efd1e7e2e6b056e4f2ddd73287a 100644 (file)
 
 #define ARCH_ID_AT91SAM9RL64   0x019b03a0
 
+#define ARCH_ID_AT91M40800     0x14080044
+#define ARCH_ID_AT91R40807     0x44080746
+#define ARCH_ID_AT91M40807     0x14080745
+#define ARCH_ID_AT91R40008     0x44000840
+
 static inline unsigned long at91_cpu_identify(void)
 {
        return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION);
index 46835e945aea0b875a9e5f252155c0d27355f381..8f1cdd38a96986fe31f9ce47a34fac0a236ca053 100644 (file)
 #include <asm/arch/at91sam9263.h>
 #elif defined(CONFIG_ARCH_AT91SAM9RL)
 #include <asm/arch/at91sam9rl.h>
+#elif defined(CONFIG_ARCH_AT91X40)
+#include <asm/arch/at91x40.h>
 #else
 #error "Unsupported AT91 processor"
 #endif
 
 
+#ifdef CONFIG_MMU
 /*
  * Remap the peripherals from address 0xFFF78000 .. 0xFFFFFFFF
  * to 0xFEF78000 .. 0xFF000000.  (544Kb)
  */
 #define AT91_IO_PHYS_BASE      0xFFF78000
-#define AT91_IO_SIZE           (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
 #define AT91_IO_VIRT_BASE      (0xFF000000 - AT91_IO_SIZE)
+#else
+/*
+ * Identity mapping for the non MMU case.
+ */
+#define AT91_IO_PHYS_BASE      AT91_BASE_SYS
+#define AT91_IO_VIRT_BASE      AT91_IO_PHYS_BASE
+#endif
+
+#define AT91_IO_SIZE           (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
 
  /* Convert a physical IO address to virtual IO address */
 #define AT91_IO_P2V(x)         ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
 #define AT91_CHIPSELECT_7      0x80000000
 
 /* SDRAM */
+#ifdef CONFIG_DRAM_BASE
+#define AT91_SDRAM_BASE                CONFIG_DRAM_BASE
+#else
 #define AT91_SDRAM_BASE                AT91_CHIPSELECT_1
+#endif
 
 /* Clocks */
 #define AT91_SLOW_CLOCK                32768           /* slow clock */
index 2df1ee12dfb797a1a70adc3a7cb4f5015eeea8b3..a310698fb4da9eb04e32b3772dd1f52a75732a8e 100644 (file)
 #define AT91SAM9_MASTER_CLOCK  100000000
 #define CLOCK_TICK_RATE                (AT91SAM9_MASTER_CLOCK/16)
 
+#elif defined(CONFIG_ARCH_AT91X40)
+
+#define AT91X40_MASTER_CLOCK   40000000
+#define CLOCK_TICK_RATE                (AT91X40_MASTER_CLOCK)
+
 #endif
 
 #endif
index 30ac587b3b41d415eeb4d11739488ec33d649314..272a7e0dc6cf928c11a4328741a03e5302441c8e 100644 (file)
  */
 static void putc(int c)
 {
+#ifdef AT91_DBGU
        void __iomem *sys = (void __iomem *) AT91_BASE_SYS;     /* physical address */
 
        while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY))
                barrier();
        __raw_writel(c, sys + AT91_DBGU_THR);
+#endif
 }
 
 static inline void flush(void)
 {
+#ifdef AT91_DBGU
        void __iomem *sys = (void __iomem *) AT91_BASE_SYS;     /* physical address */
 
        /* wait for transmission to complete */
        while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY))
                barrier();
+#endif
 }
 
 #define arch_decomp_setup()
diff --git a/include/asm-arm/arch-davinci/clock.h b/include/asm-arm/arch-davinci/clock.h
new file mode 100644 (file)
index 0000000..cc168b7
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-davinci/clock.h
+ *
+ * Clock control driver for DaVinci - header file
+ *
+ * Authors: Vladimir Barinov <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_DAVINCI_CLOCK_H
+#define __ASM_ARCH_DAVINCI_CLOCK_H
+
+struct clk;
+
+extern int clk_register(struct clk *clk);
+extern void clk_unregister(struct clk *clk);
+extern int davinci_clk_init(void);
+
+#endif
diff --git a/include/asm-arm/arch-davinci/gpio.h b/include/asm-arm/arch-davinci/gpio.h
new file mode 100644 (file)
index 0000000..ea24a0e
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef        __DAVINCI_GPIO_H
+#define        __DAVINCI_GPIO_H
+
+/*
+ * basic gpio routines
+ *
+ * board-specific init should be done by arch/.../.../board-XXX.c (maybe
+ * initializing banks together) rather than boot loaders; kexec() won't
+ * go through boot loaders.
+ *
+ * the gpio clock will be turned on when gpios are used, and you may also
+ * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are
+ * used as gpios, not with other peripherals.
+ *
+ * GPIOs are numbered 0..(DAVINCI_N_GPIO-1).  For documentation, and maybe
+ * for later updates, code should write GPIO(N) or:
+ *  - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53)
+ *  - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70)
+ *
+ * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc
+ * for now, that's != GPIO(N)
+ */
+#define        GPIO(X)         (X)             /* 0 <= X <= 70 */
+#define        GPIOV18(X)      (X)             /* 1.8V i/o; 0 <= X <= 53 */
+#define        GPIOV33(X)      ((X)+54)        /* 3.3V i/o; 0 <= X <= 17 */
+
+struct gpio_controller {
+       u32     dir;
+       u32     out_data;
+       u32     set_data;
+       u32     clr_data;
+       u32     in_data;
+       u32     set_rising;
+       u32     clr_rising;
+       u32     set_falling;
+       u32     clr_falling;
+       u32     intstat;
+};
+
+/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
+ * with constant parameters; or in outlined code they execute at runtime.
+ *
+ * You'd access the controller directly when reading or writing more than
+ * one gpio value at a time, and to support wired logic where the value
+ * being driven by the cpu need not match the value read back.
+ *
+ * These are NOT part of the cross-platform GPIO interface
+ */
+static inline struct gpio_controller *__iomem
+__gpio_to_controller(unsigned gpio)
+{
+       void *__iomem ptr;
+
+       if (gpio < 32)
+               ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
+       else if (gpio < 64)
+               ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
+       else if (gpio < DAVINCI_N_GPIO)
+               ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
+       else
+               ptr = NULL;
+       return ptr;
+}
+
+static inline u32 __gpio_mask(unsigned gpio)
+{
+       return 1 << (gpio % 32);
+}
+
+/* The get/set/clear functions will inline when called with constant
+ * parameters, for low-overhead bitbanging.  Illegal constant parameters
+ * cause link-time errors.
+ *
+ * Otherwise, calls with variable parameters use outlined functions.
+ */
+extern int __error_inval_gpio(void);
+
+extern void __gpio_set(unsigned gpio, int value);
+extern int __gpio_get(unsigned gpio);
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+       if (__builtin_constant_p(value)) {
+               struct gpio_controller  *__iomem g;
+               u32                     mask;
+
+               if (gpio >= DAVINCI_N_GPIO)
+                       __error_inval_gpio();
+
+               g = __gpio_to_controller(gpio);
+               mask = __gpio_mask(gpio);
+               if (value)
+                       __raw_writel(mask, &g->set_data);
+               else
+                       __raw_writel(mask, &g->clr_data);
+               return;
+       }
+
+       __gpio_set(gpio, value);
+}
+
+/* Returns zero or nonzero; works for gpios configured as inputs OR
+ * as outputs.
+ *
+ * NOTE: changes in reported values are synchronized to the GPIO clock.
+ * This is most easily seen after calling gpio_set_value() and then immediatly
+ * gpio_get_value(), where the gpio_get_value() would return the old value
+ * until the GPIO clock ticks and the new value gets latched.
+ */
+
+static inline int gpio_get_value(unsigned gpio)
+{
+       struct gpio_controller *__iomem g;
+
+       if (!__builtin_constant_p(gpio))
+               return __gpio_get(gpio);
+
+       if (gpio >= DAVINCI_N_GPIO)
+               return __error_inval_gpio();
+
+       g = __gpio_to_controller(gpio);
+       return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+}
+
+/* powerup default direction is IN */
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio, int value);
+
+#include <asm-generic/gpio.h>  /* cansleep wrappers */
+
+extern int gpio_request(unsigned gpio, const char *tag);
+extern void gpio_free(unsigned gpio);
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+       return DAVINCI_N_AINTC_IRQ + gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+       return irq - DAVINCI_N_AINTC_IRQ;
+}
+
+#endif                         /* __DAVINCI_GPIO_H */
index 60362d80229e66f6a12c69ec4e2455096763b15c..a2e8969afaca913c263dbb98f419dab6c3fa3799 100644 (file)
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
+/*
+ * Base register addresses
+ */
+#define DAVINCI_DMA_3PCC_BASE                  (0x01C00000)
+#define DAVINCI_DMA_3PTC0_BASE                 (0x01C10000)
+#define DAVINCI_DMA_3PTC1_BASE                 (0x01C10400)
+#define DAVINCI_I2C_BASE                       (0x01C21000)
+#define DAVINCI_PWM0_BASE                      (0x01C22000)
+#define DAVINCI_PWM1_BASE                      (0x01C22400)
+#define DAVINCI_PWM2_BASE                      (0x01C22800)
+#define DAVINCI_SYSTEM_MODULE_BASE             (0x01C40000)
+#define DAVINCI_PLL_CNTRL0_BASE                        (0x01C40800)
+#define DAVINCI_PLL_CNTRL1_BASE                        (0x01C40C00)
+#define DAVINCI_PWR_SLEEP_CNTRL_BASE           (0x01C41000)
+#define DAVINCI_SYSTEM_DFT_BASE                        (0x01C42000)
+#define DAVINCI_IEEE1394_BASE                  (0x01C60000)
+#define DAVINCI_USB_OTG_BASE                   (0x01C64000)
+#define DAVINCI_CFC_ATA_BASE                   (0x01C66000)
+#define DAVINCI_SPI_BASE                       (0x01C66800)
+#define DAVINCI_GPIO_BASE                      (0x01C67000)
+#define DAVINCI_UHPI_BASE                      (0x01C67800)
+#define DAVINCI_VPSS_REGS_BASE                 (0x01C70000)
+#define DAVINCI_EMAC_CNTRL_REGS_BASE           (0x01C80000)
+#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE   (0x01C81000)
+#define DAVINCI_EMAC_WRAPPER_RAM_BASE          (0x01C82000)
+#define DAVINCI_MDIO_CNTRL_REGS_BASE           (0x01C84000)
+#define DAVINCI_IMCOP_BASE                     (0x01CC0000)
+#define DAVINCI_ASYNC_EMIF_CNTRL_BASE          (0x01E00000)
+#define DAVINCI_VLYNQ_BASE                     (0x01E01000)
+#define DAVINCI_MCBSP_BASE                     (0x01E02000)
+#define DAVINCI_MMC_SD_BASE                    (0x01E10000)
+#define DAVINCI_MS_BASE                                (0x01E20000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE       (0x02000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE       (0x04000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE       (0x06000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE       (0x08000000)
+#define DAVINCI_VLYNQ_REMOTE_BASE              (0x0C000000)
+
 #endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-davinci/mux.h b/include/asm-arm/arch-davinci/mux.h
new file mode 100644 (file)
index 0000000..c24b678
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * DaVinci pin multiplexing defines
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_MUX_H
+#define __ASM_ARCH_MUX_H
+
+#define DAVINCI_MUX_AEAW0      0
+#define DAVINCI_MUX_AEAW1      1
+#define DAVINCI_MUX_AEAW2      2
+#define DAVINCI_MUX_AEAW3      3
+#define DAVINCI_MUX_AEAW4      4
+#define DAVINCI_MUX_AECS4      10
+#define DAVINCI_MUX_AECS5      11
+#define DAVINCI_MUX_VLYNQWD0   12
+#define DAVINCI_MUX_VLYNQWD1   13
+#define DAVINCI_MUX_VLSCREN    14
+#define DAVINCI_MUX_VLYNQEN    15
+#define DAVINCI_MUX_HDIREN     16
+#define DAVINCI_MUX_ATAEN      17
+#define DAVINCI_MUX_RGB666     22
+#define DAVINCI_MUX_RGB888     23
+#define DAVINCI_MUX_LOEEN      24
+#define DAVINCI_MUX_LFLDEN     25
+#define DAVINCI_MUX_CWEN       26
+#define DAVINCI_MUX_CFLDEN     27
+#define DAVINCI_MUX_HPIEN      29
+#define DAVINCI_MUX_1394EN     30
+#define DAVINCI_MUX_EMACEN     31
+
+#define DAVINCI_MUX_LEVEL2     32
+#define DAVINCI_MUX_UART0      (DAVINCI_MUX_LEVEL2 + 0)
+#define DAVINCI_MUX_UART1      (DAVINCI_MUX_LEVEL2 + 1)
+#define DAVINCI_MUX_UART2      (DAVINCI_MUX_LEVEL2 + 2)
+#define DAVINCI_MUX_U2FLO      (DAVINCI_MUX_LEVEL2 + 3)
+#define DAVINCI_MUX_PWM0       (DAVINCI_MUX_LEVEL2 + 4)
+#define DAVINCI_MUX_PWM1       (DAVINCI_MUX_LEVEL2 + 5)
+#define DAVINCI_MUX_PWM2       (DAVINCI_MUX_LEVEL2 + 6)
+#define DAVINCI_MUX_I2C                (DAVINCI_MUX_LEVEL2 + 7)
+#define DAVINCI_MUX_SPI                (DAVINCI_MUX_LEVEL2 + 8)
+#define DAVINCI_MUX_MSTK       (DAVINCI_MUX_LEVEL2 + 9)
+#define DAVINCI_MUX_ASP                (DAVINCI_MUX_LEVEL2 + 10)
+#define DAVINCI_MUX_CLK0       (DAVINCI_MUX_LEVEL2 + 16)
+#define DAVINCI_MUX_CLK1       (DAVINCI_MUX_LEVEL2 + 17)
+#define DAVINCI_MUX_TIMIN      (DAVINCI_MUX_LEVEL2 + 18)
+
+extern void davinci_mux_peripheral(unsigned int mux, unsigned int enable);
+
+#endif /* __ASM_ARCH_MUX_H */
diff --git a/include/asm-arm/arch-imx/gpio.h b/include/asm-arm/arch-imx/gpio.h
new file mode 100644 (file)
index 0000000..4860232
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef _IMX_GPIO_H
+
+#include <asm/arch/imx-regs.h>
+
+#define IMX_GPIO_ALLOC_MODE_NORMAL     0
+#define IMX_GPIO_ALLOC_MODE_NO_ALLOC   1
+#define IMX_GPIO_ALLOC_MODE_TRY_ALLOC  2
+#define IMX_GPIO_ALLOC_MODE_ALLOC_ONLY 4
+#define IMX_GPIO_ALLOC_MODE_RELEASE    8
+
+extern int imx_gpio_request(unsigned gpio, const char *label);
+
+extern void imx_gpio_free(unsigned gpio);
+
+extern int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+                                       int alloc_mode, const char *label);
+
+extern int imx_gpio_direction_input(unsigned gpio);
+
+extern int imx_gpio_direction_output(unsigned gpio, int value);
+
+extern void __imx_gpio_set_value(unsigned gpio, int value);
+
+static inline int imx_gpio_get_value(unsigned gpio)
+{
+       return SSR(gpio >> GPIO_PORT_SHIFT) & (1 << (gpio & GPIO_PIN_MASK));
+}
+
+static inline void imx_gpio_set_value_inline(unsigned gpio, int value)
+{
+       unsigned long flags;
+
+       raw_local_irq_save(flags);
+       if(value)
+               DR(gpio >> GPIO_PORT_SHIFT) |= (1 << (gpio & GPIO_PIN_MASK));
+       else
+               DR(gpio >> GPIO_PORT_SHIFT) &= ~(1 << (gpio & GPIO_PIN_MASK));
+       raw_local_irq_restore(flags);
+}
+
+static inline void imx_gpio_set_value(unsigned gpio, int value)
+{
+       if(__builtin_constant_p(gpio))
+               imx_gpio_set_value_inline(gpio, value);
+       else
+               __imx_gpio_set_value(gpio, value);
+}
+
+extern int imx_gpio_to_irq(unsigned gpio);
+
+extern int imx_irq_to_gpio(unsigned irq);
+
+/*-------------------------------------------------------------------------*/
+
+/* Wrappers for "new style" GPIO calls. These calls i.MX specific versions
+ * to allow future extension of GPIO logic.
+ */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+       return imx_gpio_request(gpio, label);
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+       imx_gpio_free(gpio);
+}
+
+static inline  int gpio_direction_input(unsigned gpio)
+{
+       return imx_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+       return imx_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+       return imx_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+       imx_gpio_set_value(gpio, value);
+}
+
+#include <asm-generic/gpio.h>          /* cansleep wrappers */
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+       return imx_gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+       return imx_irq_to_gpio(irq);
+}
+
+
+#endif
index 30de404c61f5ef71e1243e0dada38cbed8e277c9..fb9de27338796ab23d480cc250b86c55c27d8ed6 100644 (file)
@@ -77,6 +77,8 @@
 #define SWR(x)     __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 3) << 8)
 #define PUEN(x)    __REG2(IMX_GPIO_BASE + 0x40, ((x) & 3) << 8)
 
+#define GPIO_PORT_MAX  3
+
 #define GPIO_PIN_MASK 0x1f
 #define GPIO_PORT_MASK (0x3 << 5)
 
diff --git a/include/asm-arm/arch-iop13xx/adma.h b/include/asm-arm/arch-iop13xx/adma.h
new file mode 100644 (file)
index 0000000..04006c1
--- /dev/null
@@ -0,0 +1,544 @@
+/*
+ * Copyright(c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef _ADMA_H
+#define _ADMA_H
+#include <linux/types.h>
+#include <linux/io.h>
+#include <asm/hardware.h>
+#include <asm/hardware/iop_adma.h>
+
+#define ADMA_ACCR(chan)        (chan->mmr_base + 0x0)
+#define ADMA_ACSR(chan)        (chan->mmr_base + 0x4)
+#define ADMA_ADAR(chan)        (chan->mmr_base + 0x8)
+#define ADMA_IIPCR(chan)       (chan->mmr_base + 0x18)
+#define ADMA_IIPAR(chan)       (chan->mmr_base + 0x1c)
+#define ADMA_IIPUAR(chan)      (chan->mmr_base + 0x20)
+#define ADMA_ANDAR(chan)       (chan->mmr_base + 0x24)
+#define ADMA_ADCR(chan)        (chan->mmr_base + 0x28)
+#define ADMA_CARMD(chan)       (chan->mmr_base + 0x2c)
+#define ADMA_ABCR(chan)        (chan->mmr_base + 0x30)
+#define ADMA_DLADR(chan)       (chan->mmr_base + 0x34)
+#define ADMA_DUADR(chan)       (chan->mmr_base + 0x38)
+#define ADMA_SLAR(src, chan)   (chan->mmr_base + (0x3c + (src << 3)))
+#define ADMA_SUAR(src, chan)   (chan->mmr_base + (0x40 + (src << 3)))
+
+struct iop13xx_adma_src {
+       u32 src_addr;
+       union {
+               u32 upper_src_addr;
+               struct {
+                       unsigned int pq_upper_src_addr:24;
+                       unsigned int pq_dmlt:8;
+               };
+       };
+};
+
+struct iop13xx_adma_desc_ctrl {
+       unsigned int int_en:1;
+       unsigned int xfer_dir:2;
+       unsigned int src_select:4;
+       unsigned int zero_result:1;
+       unsigned int block_fill_en:1;
+       unsigned int crc_gen_en:1;
+       unsigned int crc_xfer_dis:1;
+       unsigned int crc_seed_fetch_dis:1;
+       unsigned int status_write_back_en:1;
+       unsigned int endian_swap_en:1;
+       unsigned int reserved0:2;
+       unsigned int pq_update_xfer_en:1;
+       unsigned int dual_xor_en:1;
+       unsigned int pq_xfer_en:1;
+       unsigned int p_xfer_dis:1;
+       unsigned int reserved1:10;
+       unsigned int relax_order_en:1;
+       unsigned int no_snoop_en:1;
+};
+
+struct iop13xx_adma_byte_count {
+       unsigned int byte_count:24;
+       unsigned int host_if:3;
+       unsigned int reserved:2;
+       unsigned int zero_result_err_q:1;
+       unsigned int zero_result_err:1;
+       unsigned int tx_complete:1;
+};
+
+struct iop13xx_adma_desc_hw {
+       u32 next_desc;
+       union {
+               u32 desc_ctrl;
+               struct iop13xx_adma_desc_ctrl desc_ctrl_field;
+       };
+       union {
+               u32 crc_addr;
+               u32 block_fill_data;
+               u32 q_dest_addr;
+       };
+       union {
+               u32 byte_count;
+               struct iop13xx_adma_byte_count byte_count_field;
+       };
+       union {
+               u32 dest_addr;
+               u32 p_dest_addr;
+       };
+       union {
+               u32 upper_dest_addr;
+               u32 pq_upper_dest_addr;
+       };
+       struct iop13xx_adma_src src[1];
+};
+
+struct iop13xx_adma_desc_dual_xor {
+       u32 next_desc;
+       u32 desc_ctrl;
+       u32 reserved;
+       u32 byte_count;
+       u32 h_dest_addr;
+       u32 h_upper_dest_addr;
+       u32 src0_addr;
+       u32 upper_src0_addr;
+       u32 src1_addr;
+       u32 upper_src1_addr;
+       u32 h_src_addr;
+       u32 h_upper_src_addr;
+       u32 d_src_addr;
+       u32 d_upper_src_addr;
+       u32 d_dest_addr;
+       u32 d_upper_dest_addr;
+};
+
+struct iop13xx_adma_desc_pq_update {
+       u32 next_desc;
+       u32 desc_ctrl;
+       u32 reserved;
+       u32 byte_count;
+       u32 p_dest_addr;
+       u32 p_upper_dest_addr;
+       u32 src0_addr;
+       u32 upper_src0_addr;
+       u32 src1_addr;
+       u32 upper_src1_addr;
+       u32 p_src_addr;
+       u32 p_upper_src_addr;
+       u32 q_src_addr;
+       struct {
+               unsigned int q_upper_src_addr:24;
+               unsigned int q_dmlt:8;
+       };
+       u32 q_dest_addr;
+       u32 q_upper_dest_addr;
+};
+
+static inline int iop_adma_get_max_xor(void)
+{
+       return 16;
+}
+
+static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
+{
+       return __raw_readl(ADMA_ADAR(chan));
+}
+
+static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
+                                               u32 next_desc_addr)
+{
+       __raw_writel(next_desc_addr, ADMA_ANDAR(chan));
+}
+
+#define ADMA_STATUS_BUSY (1 << 13)
+
+static inline char iop_chan_is_busy(struct iop_adma_chan *chan)
+{
+       if (__raw_readl(ADMA_ACSR(chan)) &
+               ADMA_STATUS_BUSY)
+               return 1;
+       else
+               return 0;
+}
+
+static inline int
+iop_chan_get_desc_align(struct iop_adma_chan *chan, int num_slots)
+{
+       return 1;
+}
+#define iop_desc_is_aligned(x, y) 1
+
+static inline int
+iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
+{
+       *slots_per_op = 1;
+       return 1;
+}
+
+#define iop_chan_interrupt_slot_count(s, c) iop_chan_memcpy_slot_count(0, s)
+
+static inline int
+iop_chan_memset_slot_count(size_t len, int *slots_per_op)
+{
+       *slots_per_op = 1;
+       return 1;
+}
+
+static inline int
+iop_chan_xor_slot_count(size_t len, int src_cnt, int *slots_per_op)
+{
+       int num_slots;
+       /* slots_to_find = 1 for basic descriptor + 1 per 4 sources above 1
+        * (1 source => 8 bytes) (1 slot => 32 bytes)
+        */
+       num_slots = 1 + (((src_cnt - 1) << 3) >> 5);
+       if (((src_cnt - 1) << 3) & 0x1f)
+               num_slots++;
+
+       *slots_per_op = num_slots;
+
+       return num_slots;
+}
+
+#define ADMA_MAX_BYTE_COUNT    (16 * 1024 * 1024)
+#define IOP_ADMA_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+#define IOP_ADMA_XOR_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+#define iop_chan_zero_sum_slot_count(l, s, o) iop_chan_xor_slot_count(l, s, o)
+
+static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc,
+                                       struct iop_adma_chan *chan)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       return hw_desc->dest_addr;
+}
+
+static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
+                                       struct iop_adma_chan *chan)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       return hw_desc->byte_count_field.byte_count;
+}
+
+static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
+                                       struct iop_adma_chan *chan,
+                                       int src_idx)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       return hw_desc->src[src_idx].src_addr;
+}
+
+static inline u32 iop_desc_get_src_count(struct iop_adma_desc_slot *desc,
+                                       struct iop_adma_chan *chan)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       return hw_desc->desc_ctrl_field.src_select + 1;
+}
+
+static inline void
+iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       union {
+               u32 value;
+               struct iop13xx_adma_desc_ctrl field;
+       } u_desc_ctrl;
+
+       u_desc_ctrl.value = 0;
+       u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+       u_desc_ctrl.field.int_en = int_en;
+       hw_desc->desc_ctrl = u_desc_ctrl.value;
+       hw_desc->crc_addr = 0;
+}
+
+static inline void
+iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       union {
+               u32 value;
+               struct iop13xx_adma_desc_ctrl field;
+       } u_desc_ctrl;
+
+       u_desc_ctrl.value = 0;
+       u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+       u_desc_ctrl.field.block_fill_en = 1;
+       u_desc_ctrl.field.int_en = int_en;
+       hw_desc->desc_ctrl = u_desc_ctrl.value;
+       hw_desc->crc_addr = 0;
+}
+
+/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
+static inline void
+iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       union {
+               u32 value;
+               struct iop13xx_adma_desc_ctrl field;
+       } u_desc_ctrl;
+
+       u_desc_ctrl.value = 0;
+       u_desc_ctrl.field.src_select = src_cnt - 1;
+       u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+       u_desc_ctrl.field.int_en = int_en;
+       hw_desc->desc_ctrl = u_desc_ctrl.value;
+       hw_desc->crc_addr = 0;
+
+}
+#define iop_desc_init_null_xor(d, s, i) iop_desc_init_xor(d, s, i)
+
+/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
+static inline int
+iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       union {
+               u32 value;
+               struct iop13xx_adma_desc_ctrl field;
+       } u_desc_ctrl;
+
+       u_desc_ctrl.value = 0;
+       u_desc_ctrl.field.src_select = src_cnt - 1;
+       u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+       u_desc_ctrl.field.zero_result = 1;
+       u_desc_ctrl.field.status_write_back_en = 1;
+       u_desc_ctrl.field.int_en = int_en;
+       hw_desc->desc_ctrl = u_desc_ctrl.value;
+       hw_desc->crc_addr = 0;
+
+       return 1;
+}
+
+static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
+                                       struct iop_adma_chan *chan,
+                                       u32 byte_count)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       hw_desc->byte_count = byte_count;
+}
+
+static inline void
+iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
+{
+       int slots_per_op = desc->slots_per_op;
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
+       int i = 0;
+
+       if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+               hw_desc->byte_count = len;
+       } else {
+               do {
+                       iter = iop_hw_desc_slot_idx(hw_desc, i);
+                       iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+                       len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+                       i += slots_per_op;
+               } while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
+
+               if (len) {
+                       iter = iop_hw_desc_slot_idx(hw_desc, i);
+                       iter->byte_count = len;
+               }
+       }
+}
+
+
+static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
+                                       struct iop_adma_chan *chan,
+                                       dma_addr_t addr)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       hw_desc->dest_addr = addr;
+       hw_desc->upper_dest_addr = 0;
+}
+
+static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
+                                       dma_addr_t addr)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       hw_desc->src[0].src_addr = addr;
+       hw_desc->src[0].upper_src_addr = 0;
+}
+
+static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
+                                       int src_idx, dma_addr_t addr)
+{
+       int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
+       int i = 0;
+
+       do {
+               iter = iop_hw_desc_slot_idx(hw_desc, i);
+               iter->src[src_idx].src_addr = addr;
+               iter->src[src_idx].upper_src_addr = 0;
+               slot_cnt -= slots_per_op;
+               if (slot_cnt) {
+                       i += slots_per_op;
+                       addr += IOP_ADMA_XOR_MAX_BYTE_COUNT;
+               }
+       } while (slot_cnt);
+}
+
+static inline void
+iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
+       struct iop_adma_chan *chan)
+{
+       iop_desc_init_memcpy(desc, 1);
+       iop_desc_set_byte_count(desc, chan, 0);
+       iop_desc_set_dest_addr(desc, chan, 0);
+       iop_desc_set_memcpy_src_addr(desc, 0);
+}
+
+#define iop_desc_set_zero_sum_src_addr iop_desc_set_xor_src_addr
+
+static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
+                                       u32 next_desc_addr)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       BUG_ON(hw_desc->next_desc);
+       hw_desc->next_desc = next_desc_addr;
+}
+
+static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       return hw_desc->next_desc;
+}
+
+static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       hw_desc->next_desc = 0;
+}
+
+static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
+                                               u32 val)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       hw_desc->block_fill_data = val;
+}
+
+static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
+{
+       struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+       struct iop13xx_adma_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
+       struct iop13xx_adma_byte_count byte_count = hw_desc->byte_count_field;
+
+       BUG_ON(!(byte_count.tx_complete && desc_ctrl.zero_result));
+
+       if (desc_ctrl.pq_xfer_en)
+               return byte_count.zero_result_err_q;
+       else
+               return byte_count.zero_result_err;
+}
+
+static inline void iop_chan_append(struct iop_adma_chan *chan)
+{
+       u32 adma_accr;
+
+       adma_accr = __raw_readl(ADMA_ACCR(chan));
+       adma_accr |= 0x2;
+       __raw_writel(adma_accr, ADMA_ACCR(chan));
+}
+
+static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
+{
+       do { } while (0);
+}
+
+static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+{
+       return __raw_readl(ADMA_ACSR(chan));
+}
+
+static inline void iop_chan_disable(struct iop_adma_chan *chan)
+{
+       u32 adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
+       adma_chan_ctrl &= ~0x1;
+       __raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
+}
+
+static inline void iop_chan_enable(struct iop_adma_chan *chan)
+{
+       u32 adma_chan_ctrl;
+
+       adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
+       adma_chan_ctrl |= 0x1;
+       __raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
+}
+
+static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
+{
+       u32 status = __raw_readl(ADMA_ACSR(chan));
+       status &= (1 << 12);
+       __raw_writel(status, ADMA_ACSR(chan));
+}
+
+static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
+{
+       u32 status = __raw_readl(ADMA_ACSR(chan));
+       status &= (1 << 11);
+       __raw_writel(status, ADMA_ACSR(chan));
+}
+
+static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
+{
+       u32 status = __raw_readl(ADMA_ACSR(chan));
+       status &= (1 << 9) | (1 << 5) | (1 << 4) | (1 << 3);
+       __raw_writel(status, ADMA_ACSR(chan));
+}
+
+static inline int
+iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
+{
+       return test_bit(9, &status);
+}
+
+static inline int
+iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
+{
+       return test_bit(5, &status);
+}
+
+static inline int
+iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+       return test_bit(4, &status);
+}
+
+static inline int
+iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+       return test_bit(3, &status);
+}
+
+static inline int
+iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+       return 0;
+}
+
+static inline int
+iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+       return 0;
+}
+
+static inline int
+iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
+{
+       return 0;
+}
+
+#endif /* _ADMA_H */
index e6736c3d1f7f449b258eb3e35a978a877fc24196..d4e4f828577cc51c41bb23221fd15960026f9d88 100644 (file)
@@ -166,12 +166,22 @@ static inline int iop13xx_cpu_id(void)
 #define IOP13XX_INIT_I2C_1           (1 << 1)
 #define IOP13XX_INIT_I2C_2           (1 << 2)
 
-#define IQ81340_NUM_UART     2
-#define IQ81340_NUM_I2C      3
-#define IQ81340_NUM_PHYS_MAP_FLASH 1
-#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART +\
-                               IQ81340_NUM_I2C +\
-                               IQ81340_NUM_PHYS_MAP_FLASH)
+/* ADMA selection flags */
+/* INIT_ADMA_DEFAULT = Rely on CONFIG_IOP13XX_ADMA* */
+#define IOP13XX_INIT_ADMA_DEFAULT     (0)
+#define IOP13XX_INIT_ADMA_0           (1 << 0)
+#define IOP13XX_INIT_ADMA_1           (1 << 1)
+#define IOP13XX_INIT_ADMA_2           (1 << 2)
+
+/* Platform devices */
+#define IQ81340_NUM_UART               2
+#define IQ81340_NUM_I2C                3
+#define IQ81340_NUM_PHYS_MAP_FLASH     1
+#define IQ81340_NUM_ADMA               3
+#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART + \
+                               IQ81340_NUM_I2C + \
+                               IQ81340_NUM_PHYS_MAP_FLASH + \
+                               IQ81340_NUM_ADMA)
 
 /*========================== PMMR offsets for key registers ============*/
 #define IOP13XX_ATU0_PMMR_OFFSET       0x00048000
@@ -444,22 +454,6 @@ static inline int iop13xx_cpu_id(void)
 /*==============================ADMA UNITS===============================*/
 #define IOP13XX_ADMA_PHYS_BASE(chan)   IOP13XX_REG_ADDR32_PHYS((chan << 9))
 #define IOP13XX_ADMA_UPPER_PA(chan)    (IOP13XX_ADMA_PHYS_BASE(chan) + 0xc0)
-#define IOP13XX_ADMA_OFFSET(chan, ofs) IOP13XX_REG_ADDR32((chan << 9) + (ofs))
-
-#define IOP13XX_ADMA_ACCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x0)
-#define IOP13XX_ADMA_ACSR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x4)
-#define IOP13XX_ADMA_ADAR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x8)
-#define IOP13XX_ADMA_IIPCR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x18)
-#define IOP13XX_ADMA_IIPAR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x1c)
-#define IOP13XX_ADMA_IIPUAR(chan)    IOP13XX_ADMA_OFFSET(chan, 0x20)
-#define IOP13XX_ADMA_ANDAR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x24)
-#define IOP13XX_ADMA_ADCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x28)
-#define IOP13XX_ADMA_CARMD(chan)     IOP13XX_ADMA_OFFSET(chan, 0x2c)
-#define IOP13XX_ADMA_ABCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x30)
-#define IOP13XX_ADMA_DLADR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x34)
-#define IOP13XX_ADMA_DUADR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x38)
-#define IOP13XX_ADMA_SLAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x3c + (src <<3))
-#define IOP13XX_ADMA_SUAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x40 + (src <<3))
 
 /*==============================XSI BRIDGE===============================*/
 #define IOP13XX_XBG_BECSR              IOP13XX_REG_ADDR32(0x178c)
diff --git a/include/asm-arm/arch-iop32x/adma.h b/include/asm-arm/arch-iop32x/adma.h
new file mode 100644 (file)
index 0000000..5ed9203
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef IOP32X_ADMA_H
+#define IOP32X_ADMA_H
+#include <asm/hardware/iop3xx-adma.h>
+#endif
+
diff --git a/include/asm-arm/arch-iop33x/adma.h b/include/asm-arm/arch-iop33x/adma.h
new file mode 100644 (file)
index 0000000..4b92f79
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef IOP33X_ADMA_H
+#define IOP33X_ADMA_H
+#include <asm/hardware/iop3xx-adma.h>
+#endif
+
index 3d3820d7ba09f71847bb9256aac2c6a7bb71b1ea..e0791af3bfead32bd7483965281dc68b353d9c47 100644 (file)
@@ -32,4 +32,8 @@
 #define        IXDP425_PCI_INTC_PIN    9
 #define        IXDP425_PCI_INTD_PIN    8
 
+/* NAND Flash pins */
+#define        IXDP425_NAND_NCE_PIN    12
 
+#define        IXDP425_NAND_CMD_BYTE   0x01
+#define        IXDP425_NAND_ADDR_BYTE  0x02
index 79b850a3be475cdb96422c85be26d3170d8e8307..dbdec36ff0d1bc7642dd64c662ea17262a52a13a 100644 (file)
@@ -6,25 +6,3 @@
 
 extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info);
 
-static inline int udc_gpio_to_irq(unsigned gpio)
-{
-       return 0;
-}
-
-static inline void udc_gpio_init_vbus(unsigned gpio)
-{
-}
-
-static inline void udc_gpio_init_pullup(unsigned gpio)
-{
-}
-
-static inline int udc_gpio_get(unsigned gpio)
-{
-       return 0;
-}
-
-static inline void udc_gpio_set(unsigned gpio, int is_on)
-{
-}
-
index 09ae6c91be60b075c3e972b383841515a9506900..f7a35b78823ff0227c44c6e4d9cc4d6052408ddd 100644 (file)
@@ -38,9 +38,10 @@ static void flush(void)
 static __inline__ void __arch_decomp_setup(unsigned long arch_id)
 {
        /*
-        * Coyote and gtwx5715 only have UART2 connected
+        * Some boards are using UART2 as console
         */
-       if (machine_is_adi_coyote() || machine_is_gtwx5715())
+       if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
+                        machine_is_gateway7001() || machine_is_wg302v2())
                uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
        else
                uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
diff --git a/include/asm-arm/arch-ks8695/gpio.h b/include/asm-arm/arch-ks8695/gpio.h
new file mode 100644 (file)
index 0000000..65ceea2
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * include/asm-arm/arch-ks8695/gpio.h
+ *
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_GPIO_H_
+#define __ASM_ARCH_GPIO_H_
+
+#define KS8695_GPIO_0          0
+#define KS8695_GPIO_1          1
+#define KS8695_GPIO_2          2
+#define KS8695_GPIO_3          3
+#define KS8695_GPIO_4          4
+#define KS8695_GPIO_5          5
+#define KS8695_GPIO_6          6
+#define KS8695_GPIO_7          7
+#define KS8695_GPIO_8          8
+#define KS8695_GPIO_9          9
+#define KS8695_GPIO_10         10
+#define KS8695_GPIO_11         11
+#define KS8695_GPIO_12         12
+#define KS8695_GPIO_13         13
+#define KS8695_GPIO_14         14
+#define KS8695_GPIO_15         15
+
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
+
+/*
+ * Configure the GPIO line as an input.
+ */
+int __init_or_module gpio_direction_input(unsigned int pin);
+
+/*
+ * Configure the GPIO line as an output, with default state.
+ */
+int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state);
+
+/*
+ * Set the state of an output GPIO line.
+ */
+void gpio_set_value(unsigned int pin, unsigned int state);
+
+/*
+ * Read the state of a GPIO line.
+ */
+int gpio_get_value(unsigned int pin);
+
+/*
+ * Map GPIO line to IRQ number.
+ */
+int gpio_to_irq(unsigned int pin);
+
+/*
+ * Map IRQ number to GPIO line.
+ */
+int irq_to_gpio(unsigned int irq);
+
+
+#include <asm-generic/gpio.h>
+
+static inline int gpio_request(unsigned int pin, const char *label)
+{
+       return 0;
+}
+
+static inline void gpio_free(unsigned int pin)
+{
+}
+
+#endif
index bed042d71d68dd7154e5cf5ed0c4035230858706..3280ee2ddfa591cbbbe42e1336c7b89f4627e2aa 100644 (file)
@@ -30,30 +30,12 @@ typedef enum {
        DMA_PRIO_LOW = 2
 } pxa_dma_prio;
 
-#if defined(CONFIG_PXA27x)
-
-#define PXA_DMA_CHANNELS       32
-
-#define pxa_for_each_dma_prio(ch, prio)                                        \
-for (                                                                  \
-       ch = prio * 4;                                                  \
-       ch != (4 << prio) + 16;                                         \
-       ch = (ch + 1 == (4 << prio)) ? (prio * 4 + 16) : (ch + 1)       \
-)
-
-#elif defined(CONFIG_PXA25x)
-
-#define PXA_DMA_CHANNELS       16
-
-#define pxa_for_each_dma_prio(ch, prio)                                        \
-       for (ch = prio * 4; ch != (4 << prio); ch++)
-
-#endif
-
 /*
  * DMA registration
  */
 
+int __init pxa_init_dma(int num_ch);
+
 int pxa_request_dma (char *name,
                         pxa_dma_prio prio,
                         void (*irq_handler)(int, void *),
index 1d5fbb9b379a03652b3c8347ef1adaed15bce146..b7e730851461d635f38eff192b9ab6011053f98f 100644 (file)
                .endm
 
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-#ifdef CONFIG_PXA27x
-               mrc     p6, 0, \irqstat, c0, c0, 0              @ ICIP
-               mrc     p6, 0, \irqnr, c1, c0, 0                @ ICMR
-#else
+               mrc     p15, 0, \tmp, c0, c0, 0         @ CPUID
+               mov     \tmp, \tmp, lsr #13
+               and     \tmp, \tmp, #0x7                @ Core G
+               cmp     \tmp, #1
+               bhi     1004f
+
                mov     \base, #io_p2v(0x40000000)      @ IIR Ctl = 0x40d00000
                add     \base, \base, #0x00d00000
                ldr     \irqstat, [\base, #0]           @ ICIP
                ldr     \irqnr, [\base, #4]             @ ICMR
-#endif
+               b       1002f
+
+1004:
+               mrc     p6, 0, \irqstat, c6, c0, 0      @ ICIP2
+               mrc     p6, 0, \irqnr, c7, c0, 0        @ ICMR2
+               ands    \irqstat, \irqstat, \irqnr
+               beq     1003f
+               rsb     \irqstat, \irqnr, #0
+               and     \irqstat, \irqstat, \irqnr
+               clz     \irqnr, \irqstat
+               rsb     \irqnr, \irqnr, #31
+               add     \irqnr, \irqnr, #32
+               b       1001f
+1003:
+               mrc     p6, 0, \irqstat, c0, c0, 0      @ ICIP
+               mrc     p6, 0, \irqnr, c1, c0, 0        @ ICMR
+1002:
                ands    \irqnr, \irqstat, \irqnr
                beq     1001f
                rsb     \irqstat, \irqnr, #0
                and     \irqstat, \irqstat, \irqnr
                clz     \irqnr, \irqstat
-               rsb     \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
+               rsb     \irqnr, \irqnr, #31
 1001:
                .endm
index e2bdc2fbede1efdd52e1a393601edb3c2f5f4e91..386121746417093c90d6807bda3cc90d3d2c7e91 100644 (file)
 
 #ifndef __ASSEMBLY__
 
+#define __cpu_is_pxa21x(id)                            \
+       ({                                              \
+               unsigned int _id = (id) >> 4 & 0xf3f;   \
+               _id == 0x212;                           \
+       })
+
+#define __cpu_is_pxa25x(id)                            \
+       ({                                              \
+               unsigned int _id = (id) >> 4 & 0xfff;   \
+               _id == 0x2d0 || _id == 0x290;           \
+       })
+
+#define __cpu_is_pxa27x(id)                            \
+       ({                                              \
+               unsigned int _id = (id) >> 4 & 0xfff;   \
+               _id == 0x411;                           \
+       })
+
+#define cpu_is_pxa21x()                                        \
+       ({                                              \
+               unsigned int id = read_cpuid(CPUID_ID); \
+               __cpu_is_pxa21x(id);                    \
+       })
+
+#define cpu_is_pxa25x()                                        \
+       ({                                              \
+               unsigned int id = read_cpuid(CPUID_ID); \
+               __cpu_is_pxa25x(id);                    \
+       })
+
+#define cpu_is_pxa27x()                                        \
+       ({                                              \
+               unsigned int id = read_cpuid(CPUID_ID); \
+               __cpu_is_pxa27x(id);                    \
+       })
+
 /*
  * Handy routine to set GPIO alternate functions
  */
index 67ed43674c635a66a3a947accb3a757810fdd260..a07fe0f928cd1f4fdea379338ba18d5d4f0675ae 100644 (file)
  */
 
 
-#ifdef CONFIG_PXA27x
-#define PXA_IRQ_SKIP   0
-#else
-#define PXA_IRQ_SKIP   7
-#endif
-
-#define PXA_IRQ(x)     ((x) - PXA_IRQ_SKIP)
+#define PXA_IRQ(x)     (x)
 
+#ifdef CONFIG_PXA27x
 #define IRQ_SSP3       PXA_IRQ(0)      /* SSP3 service request */
 #define IRQ_MSL                PXA_IRQ(1)      /* MSL Interface interrupt */
 #define IRQ_USBH2      PXA_IRQ(2)      /* USB Host interrupt 1 (OHCI) */
@@ -26,6 +21,8 @@
 #define IRQ_KEYPAD     PXA_IRQ(4)      /* Key pad controller */
 #define IRQ_MEMSTK     PXA_IRQ(5)      /* Memory Stick interrupt */
 #define IRQ_PWRI2C     PXA_IRQ(6)      /* Power I2C interrupt */
+#endif
+
 #define IRQ_HWUART     PXA_IRQ(7)      /* HWUART Transmit/Receive/Error (PXA26x) */
 #define IRQ_OST_4_11   PXA_IRQ(7)      /* OS timer 4-11 matches (PXA27x) */
 #define        IRQ_GPIO0       PXA_IRQ(8)      /* GPIO0 Edge Detect */
 #ifdef CONFIG_PXA27x
 #define IRQ_TPM                PXA_IRQ(32)     /* TPM interrupt */
 #define IRQ_CAMERA     PXA_IRQ(33)     /* Camera Interface */
-
-#define PXA_INTERNAL_IRQS 34
-#else
-#define PXA_INTERNAL_IRQS 32
 #endif
 
-#define GPIO_2_x_TO_IRQ(x)     \
-                       PXA_IRQ((x) - 2 + PXA_INTERNAL_IRQS)
+#define PXA_GPIO_IRQ_BASE      (64)
+#define PXA_GPIO_IRQ_NUM       (128)
+
+#define GPIO_2_x_TO_IRQ(x)     (PXA_GPIO_IRQ_BASE + (x))
 #define IRQ_GPIO(x)    (((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_x_TO_IRQ(x))
 
-#define IRQ_TO_GPIO_2_x(i)     \
-                       ((i) - IRQ_GPIO(2) + 2)
+#define IRQ_TO_GPIO_2_x(i)     ((i) - PXA_GPIO_IRQ_BASE)
 #define IRQ_TO_GPIO(i) (((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
 
 #if defined(CONFIG_PXA25x)
@@ -84,7 +78,7 @@
  * these.  If you need more, increase IRQ_BOARD_END, but keep it
  * within sensible limits.
  */
-#define IRQ_BOARD_START                (IRQ_GPIO(PXA_LAST_GPIO) + 1)
+#define IRQ_BOARD_START                (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
 #define IRQ_BOARD_END          (IRQ_BOARD_START + 16)
 
 #define IRQ_SA1111_START       (IRQ_BOARD_END)
index 7a8a1cdf430ddaaf80d1bf9939b5975fa49d9e7b..52243a62c4e76de36fbe21f8aa10d4846684e283 100644 (file)
@@ -9,4 +9,3 @@
 
 extern int pxa_pm_prepare(suspend_state_t state);
 extern int pxa_pm_enter(suspend_state_t state);
-extern int pxa_pm_finish(suspend_state_t state);
index dbcc9298b0c89b7cc5880fd3d9a420fe4d89f3fc..e68b593d69da28638390fa3d89b55425fc032ea9 100644 (file)
 #define SSACD_P(x) (*(((x) == 1) ? &SSACD_P1 : ((x) == 2) ? &SSACD_P2 : ((x) == 3) ? &SSACD_P3 : NULL))
 
 /*
- * MultiMediaCard (MMC) controller
+ * MultiMediaCard (MMC) controller - see drivers/mmc/host/pxamci.h
  */
 
-#define MMC_STRPCL     __REG(0x41100000)  /* Control to start and stop MMC clock */
-#define MMC_STAT       __REG(0x41100004)  /* MMC Status Register (read only) */
-#define MMC_CLKRT      __REG(0x41100008)  /* MMC clock rate */
-#define MMC_SPI                __REG(0x4110000c)  /* SPI mode control bits */
-#define MMC_CMDAT      __REG(0x41100010)  /* Command/response/data sequence control */
-#define MMC_RESTO      __REG(0x41100014)  /* Expected response time out */
-#define MMC_RDTO       __REG(0x41100018)  /* Expected data read time out */
-#define MMC_BLKLEN     __REG(0x4110001c)  /* Block length of data transaction */
-#define MMC_NOB                __REG(0x41100020)  /* Number of blocks, for block mode */
-#define MMC_PRTBUF     __REG(0x41100024)  /* Partial MMC_TXFIFO FIFO written */
-#define MMC_I_MASK     __REG(0x41100028)  /* Interrupt Mask */
-#define MMC_I_REG      __REG(0x4110002c)  /* Interrupt Register (read only) */
-#define MMC_CMD                __REG(0x41100030)  /* Index of current command */
-#define MMC_ARGH       __REG(0x41100034)  /* MSW part of the current command argument */
-#define MMC_ARGL       __REG(0x41100038)  /* LSW part of the current command argument */
-#define MMC_RES                __REG(0x4110003c)  /* Response FIFO (read only) */
-#define MMC_RXFIFO     __REG(0x41100040)  /* Receive FIFO (read only) */
-#define MMC_TXFIFO     __REG(0x41100044)  /* Transmit FIFO (write only) */
-
-
 /*
  * Core Clock
  */
index 8bc6f9c3e3ea2c130b271b46359e7b0a34f7d3bc..27aa3a91012f88ac966edfa7a38a1c1e895fcc03 100644 (file)
@@ -1,41 +1,8 @@
 /*
  * linux/include/asm-arm/arch-pxa/udc.h
  *
- * This supports machine-specific differences in how the PXA2xx
- * USB Device Controller (UDC) is wired.
- *
  */
 #include <asm/mach/udc_pxa2xx.h>
 
 extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
 
-static inline int udc_gpio_to_irq(unsigned gpio)
-{
-       return IRQ_GPIO(gpio & GPIO_MD_MASK_NR);
-}
-
-static inline void udc_gpio_init_vbus(unsigned gpio)
-{
-       pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_IN);
-}
-
-static inline void udc_gpio_init_pullup(unsigned gpio)
-{
-       pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_OUT | GPIO_DFLT_LOW);
-}
-
-static inline int udc_gpio_get(unsigned gpio)
-{
-       return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
-}
-
-static inline void udc_gpio_set(unsigned gpio, int is_on)
-{
-       int mask = GPIO_bit(gpio);
-
-       if (is_on)
-               GPSR(gpio) = mask;
-       else
-               GPCR(gpio) = mask;
-}
-
index 3679a8a8922ee97778818e9fe75e7dd6ba4cf195..d7a777f05088d6332a3a723a7308f3c82070a7cd 100644 (file)
@@ -7,6 +7,7 @@
  */
 #include <asm/ptrace.h>
 #include <asm/user.h>
+#include <asm/hwcap.h>
 
 typedef unsigned long elf_greg_t;
 typedef unsigned long elf_freg_t[3];
@@ -39,30 +40,8 @@ typedef struct user_fp elf_fpregset_t;
 #endif
 #define ELF_ARCH       EM_ARM
 
-/*
- * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
- */
-#define HWCAP_SWP      1
-#define HWCAP_HALF     2
-#define HWCAP_THUMB    4
-#define HWCAP_26BIT    8       /* Play it safe */
-#define HWCAP_FAST_MULT        16
-#define HWCAP_FPA      32
-#define HWCAP_VFP      64
-#define HWCAP_EDSP     128
-#define HWCAP_JAVA     256
-#define HWCAP_IWMMXT   512
-#define HWCAP_CRUNCH   1024
-
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
-/*
- * This yields a mask that user programs can use to figure out what
- * instruction set this cpu supports.
- */
-#define ELF_HWCAP      (elf_hwcap)
-extern unsigned int elf_hwcap;
-
 /*
  * This yields a string that ld.so will use to load implementation
  * specific libraries for optimization.  This is more specific in
diff --git a/include/asm-arm/hardware/iop3xx-adma.h b/include/asm-arm/hardware/iop3xx-adma.h
new file mode 100644 (file)
index 0000000..10834b5
--- /dev/null
@@ -0,0 +1,892 @@
+/*
+ * Copyright Â© 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef _ADMA_H
+#define _ADMA_H
+#include <linux/types.h>
+#include <linux/io.h>
+#include <asm/hardware.h>
+#include <asm/hardware/iop_adma.h>
+
+/* Memory copy units */
+#define DMA_CCR(chan)          (chan->mmr_base + 0x0)
+#define DMA_CSR(chan)          (chan->mmr_base + 0x4)
+#define DMA_DAR(chan)          (chan->mmr_base + 0xc)
+#define DMA_NDAR(chan)         (chan->mmr_base + 0x10)
+#define DMA_PADR(chan)         (chan->mmr_base + 0x14)
+#define DMA_PUADR(chan)        (chan->mmr_base + 0x18)
+#define DMA_LADR(chan)         (chan->mmr_base + 0x1c)
+#define DMA_BCR(chan)          (chan->mmr_base + 0x20)
+#define DMA_DCR(chan)          (chan->mmr_base + 0x24)
+
+/* Application accelerator unit  */
+#define AAU_ACR(chan)          (chan->mmr_base + 0x0)
+#define AAU_ASR(chan)          (chan->mmr_base + 0x4)
+#define AAU_ADAR(chan)         (chan->mmr_base + 0x8)
+#define AAU_ANDAR(chan)        (chan->mmr_base + 0xc)
+#define AAU_SAR(src, chan)     (chan->mmr_base + (0x10 + ((src) << 2)))
+#define AAU_DAR(chan)          (chan->mmr_base + 0x20)
+#define AAU_ABCR(chan)         (chan->mmr_base + 0x24)
+#define AAU_ADCR(chan)         (chan->mmr_base + 0x28)
+#define AAU_SAR_EDCR(src_edc)  (chan->mmr_base + (0x02c + ((src_edc-4) << 2)))
+#define AAU_EDCR0_IDX  8
+#define AAU_EDCR1_IDX  17
+#define AAU_EDCR2_IDX  26
+
+#define DMA0_ID 0
+#define DMA1_ID 1
+#define AAU_ID 2
+
+struct iop3xx_aau_desc_ctrl {
+       unsigned int int_en:1;
+       unsigned int blk1_cmd_ctrl:3;
+       unsigned int blk2_cmd_ctrl:3;
+       unsigned int blk3_cmd_ctrl:3;
+       unsigned int blk4_cmd_ctrl:3;
+       unsigned int blk5_cmd_ctrl:3;
+       unsigned int blk6_cmd_ctrl:3;
+       unsigned int blk7_cmd_ctrl:3;
+       unsigned int blk8_cmd_ctrl:3;
+       unsigned int blk_ctrl:2;
+       unsigned int dual_xor_en:1;
+       unsigned int tx_complete:1;
+       unsigned int zero_result_err:1;
+       unsigned int zero_result_en:1;
+       unsigned int dest_write_en:1;
+};
+
+struct iop3xx_aau_e_desc_ctrl {
+       unsigned int reserved:1;
+       unsigned int blk1_cmd_ctrl:3;
+       unsigned int blk2_cmd_ctrl:3;
+       unsigned int blk3_cmd_ctrl:3;
+       unsigned int blk4_cmd_ctrl:3;
+       unsigned int blk5_cmd_ctrl:3;
+       unsigned int blk6_cmd_ctrl:3;
+       unsigned int blk7_cmd_ctrl:3;
+       unsigned int blk8_cmd_ctrl:3;
+       unsigned int reserved2:7;
+};
+
+struct iop3xx_dma_desc_ctrl {
+       unsigned int pci_transaction:4;
+       unsigned int int_en:1;
+       unsigned int dac_cycle_en:1;
+       unsigned int mem_to_mem_en:1;
+       unsigned int crc_data_tx_en:1;
+       unsigned int crc_gen_en:1;
+       unsigned int crc_seed_dis:1;
+       unsigned int reserved:21;
+       unsigned int crc_tx_complete:1;
+};
+
+struct iop3xx_desc_dma {
+       u32 next_desc;
+       union {
+               u32 pci_src_addr;
+               u32 pci_dest_addr;
+               u32 src_addr;
+       };
+       union {
+               u32 upper_pci_src_addr;
+               u32 upper_pci_dest_addr;
+       };
+       union {
+               u32 local_pci_src_addr;
+               u32 local_pci_dest_addr;
+               u32 dest_addr;
+       };
+       u32 byte_count;
+       union {
+               u32 desc_ctrl;
+               struct iop3xx_dma_desc_ctrl desc_ctrl_field;
+       };
+       u32 crc_addr;
+};
+
+struct iop3xx_desc_aau {
+       u32 next_desc;
+       u32 src[4];
+       u32 dest_addr;
+       u32 byte_count;
+       union {
+               u32 desc_ctrl;
+               struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+       };
+       union {
+               u32 src_addr;
+               u32 e_desc_ctrl;
+               struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
+       } src_edc[31];
+};
+
+struct iop3xx_aau_gfmr {
+       unsigned int gfmr1:8;
+       unsigned int gfmr2:8;
+       unsigned int gfmr3:8;
+       unsigned int gfmr4:8;
+};
+
+struct iop3xx_desc_pq_xor {
+       u32 next_desc;
+       u32 src[3];
+       union {
+               u32 data_mult1;
+               struct iop3xx_aau_gfmr data_mult1_field;
+       };
+       u32 dest_addr;
+       u32 byte_count;
+       union {
+               u32 desc_ctrl;
+               struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+       };
+       union {
+               u32 src_addr;
+               u32 e_desc_ctrl;
+               struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
+               u32 data_multiplier;
+               struct iop3xx_aau_gfmr data_mult_field;
+               u32 reserved;
+       } src_edc_gfmr[19];
+};
+
+struct iop3xx_desc_dual_xor {
+       u32 next_desc;
+       u32 src0_addr;
+       u32 src1_addr;
+       u32 h_src_addr;
+       u32 d_src_addr;
+       u32 h_dest_addr;
+       u32 byte_count;
+       union {
+               u32 desc_ctrl;
+               struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+       };
+       u32 d_dest_addr;
+};
+
+union iop3xx_desc {
+       struct iop3xx_desc_aau *aau;
+       struct iop3xx_desc_dma *dma;
+       struct iop3xx_desc_pq_xor *pq_xor;
+       struct iop3xx_desc_dual_xor *dual_xor;
+       void *ptr;
+};
+
+static inline int iop_adma_get_max_xor(void)
+{
+       return 32;
+}
+
+static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
+{
+       int id = chan->device->id;
+
+       switch (id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               return __raw_readl(DMA_DAR(chan));
+       case AAU_ID:
+               return __raw_readl(AAU_ADAR(chan));
+       default:
+               BUG();
+       }
+       return 0;
+}
+
+static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
+                                               u32 next_desc_addr)
+{
+       int id = chan->device->id;
+
+       switch (id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               __raw_writel(next_desc_addr, DMA_NDAR(chan));
+               break;
+       case AAU_ID:
+               __raw_writel(next_desc_addr, AAU_ANDAR(chan));
+               break;
+       }
+
+}
+
+#define IOP_ADMA_STATUS_BUSY (1 << 10)
+#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT (1024)
+#define IOP_ADMA_XOR_MAX_BYTE_COUNT (16 * 1024 * 1024)
+#define IOP_ADMA_MAX_BYTE_COUNT (16 * 1024 * 1024)
+
+static inline int iop_chan_is_busy(struct iop_adma_chan *chan)
+{
+       u32 status = __raw_readl(DMA_CSR(chan));
+       return (status & IOP_ADMA_STATUS_BUSY) ? 1 : 0;
+}
+
+static inline int iop_desc_is_aligned(struct iop_adma_desc_slot *desc,
+                                       int num_slots)
+{
+       /* num_slots will only ever be 1, 2, 4, or 8 */
+       return (desc->idx & (num_slots - 1)) ? 0 : 1;
+}
+
+/* to do: support large (i.e. > hw max) buffer sizes */
+static inline int iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
+{
+       *slots_per_op = 1;
+       return 1;
+}
+
+/* to do: support large (i.e. > hw max) buffer sizes */
+static inline int iop_chan_memset_slot_count(size_t len, int *slots_per_op)
+{
+       *slots_per_op = 1;
+       return 1;
+}
+
+static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
+                                       int *slots_per_op)
+{
+       const static int slot_count_table[] = { 0,
+                                               1, 1, 1, 1, /* 01 - 04 */
+                                               2, 2, 2, 2, /* 05 - 08 */
+                                               4, 4, 4, 4, /* 09 - 12 */
+                                               4, 4, 4, 4, /* 13 - 16 */
+                                               8, 8, 8, 8, /* 17 - 20 */
+                                               8, 8, 8, 8, /* 21 - 24 */
+                                               8, 8, 8, 8, /* 25 - 28 */
+                                               8, 8, 8, 8, /* 29 - 32 */
+                                             };
+       *slots_per_op = slot_count_table[src_cnt];
+       return *slots_per_op;
+}
+
+static inline int
+iop_chan_interrupt_slot_count(int *slots_per_op, struct iop_adma_chan *chan)
+{
+       switch (chan->device->id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               return iop_chan_memcpy_slot_count(0, slots_per_op);
+       case AAU_ID:
+               return iop3xx_aau_xor_slot_count(0, 2, slots_per_op);
+       default:
+               BUG();
+       }
+       return 0;
+}
+
+static inline int iop_chan_xor_slot_count(size_t len, int src_cnt,
+                                               int *slots_per_op)
+{
+       int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
+
+       if (len <= IOP_ADMA_XOR_MAX_BYTE_COUNT)
+               return slot_cnt;
+
+       len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
+       while (len > IOP_ADMA_XOR_MAX_BYTE_COUNT) {
+               len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
+               slot_cnt += *slots_per_op;
+       }
+
+       if (len)
+               slot_cnt += *slots_per_op;
+
+       return slot_cnt;
+}
+
+/* zero sum on iop3xx is limited to 1k at a time so it requires multiple
+ * descriptors
+ */
+static inline int iop_chan_zero_sum_slot_count(size_t len, int src_cnt,
+                                               int *slots_per_op)
+{
+       int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
+
+       if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT)
+               return slot_cnt;
+
+       len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+       while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+               len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+               slot_cnt += *slots_per_op;
+       }
+
+       if (len)
+               slot_cnt += *slots_per_op;
+
+       return slot_cnt;
+}
+
+static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc,
+                                       struct iop_adma_chan *chan)
+{
+       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+       switch (chan->device->id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               return hw_desc.dma->dest_addr;
+       case AAU_ID:
+               return hw_desc.aau->dest_addr;
+       default:
+               BUG();
+       }
+       return 0;
+}
+
+static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
+                                       struct iop_adma_chan *chan)
+{
+       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+       switch (chan->device->id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               return hw_desc.dma->byte_count;
+       case AAU_ID:
+               return hw_desc.aau->byte_count;
+       default:
+               BUG();
+       }
+       return 0;
+}
+
+/* translate the src_idx to a descriptor word index */
+static inline int __desc_idx(int src_idx)
+{
+       const static int desc_idx_table[] = { 0, 0, 0, 0,
+                                             0, 1, 2, 3,
+                                             5, 6, 7, 8,
+                                             9, 10, 11, 12,
+                                             14, 15, 16, 17,
+                                             18, 19, 20, 21,
+                                             23, 24, 25, 26,
+                                             27, 28, 29, 30,
+                                           };
+
+       return desc_idx_table[src_idx];
+}
+
+static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
+                                       struct iop_adma_chan *chan,
+                                       int src_idx)
+{
+       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+       switch (chan->device->id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               return hw_desc.dma->src_addr;
+       case AAU_ID:
+               break;
+       default:
+               BUG();
+       }
+
+       if (src_idx < 4)
+               return hw_desc.aau->src[src_idx];
+       else
+               return hw_desc.aau->src_edc[__desc_idx(src_idx)].src_addr;
+}
+
+static inline void iop3xx_aau_desc_set_src_addr(struct iop3xx_desc_aau *hw_desc,
+                                       int src_idx, dma_addr_t addr)
+{
+       if (src_idx < 4)
+               hw_desc->src[src_idx] = addr;
+       else
+               hw_desc->src_edc[__desc_idx(src_idx)].src_addr = addr;
+}
+
+static inline void
+iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
+{
+       struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
+       union {
+               u32 value;
+               struct iop3xx_dma_desc_ctrl field;
+       } u_desc_ctrl;
+
+       u_desc_ctrl.value = 0;
+       u_desc_ctrl.field.mem_to_mem_en = 1;
+       u_desc_ctrl.field.pci_transaction = 0xe; /* memory read block */
+       u_desc_ctrl.field.int_en = int_en;
+       hw_desc->desc_ctrl = u_desc_ctrl.value;
+       hw_desc->upper_pci_src_addr = 0;
+       hw_desc->crc_addr = 0;
+}
+
+static inline void
+iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
+{
+       struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+       union {
+               u32 value;
+               struct iop3xx_aau_desc_ctrl field;
+       } u_desc_ctrl;
+
+       u_desc_ctrl.value = 0;
+       u_desc_ctrl.field.blk1_cmd_ctrl = 0x2; /* memory block fill */
+       u_desc_ctrl.field.dest_write_en = 1;
+       u_desc_ctrl.field.int_en = int_en;
+       hw_desc->desc_ctrl = u_desc_ctrl.value;
+}
+
+static inline u32
+iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt, int int_en)
+{
+       int i, shift;
+       u32 edcr;
+       union {
+               u32 value;
+               struct iop3xx_aau_desc_ctrl field;
+       } u_desc_ctrl;
+
+       u_desc_ctrl.value = 0;
+       switch (src_cnt) {
+       case 25 ... 32:
+               u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+               edcr = 0;
+               shift = 1;
+               for (i = 24; i < src_cnt; i++) {
+                       edcr |= (1 << shift);
+                       shift += 3;
+               }
+               hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = edcr;
+               src_cnt = 24;
+               /* fall through */
+       case 17 ... 24:
+               if (!u_desc_ctrl.field.blk_ctrl) {
+                       hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+                       u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+               }
+               edcr = 0;
+               shift = 1;
+               for (i = 16; i < src_cnt; i++) {
+                       edcr |= (1 << shift);
+                       shift += 3;
+               }
+               hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = edcr;
+               src_cnt = 16;
+               /* fall through */
+       case 9 ... 16:
+               if (!u_desc_ctrl.field.blk_ctrl)
+                       u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
+               edcr = 0;
+               shift = 1;
+               for (i = 8; i < src_cnt; i++) {
+                       edcr |= (1 << shift);
+                       shift += 3;
+               }
+               hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = edcr;
+               src_cnt = 8;
+               /* fall through */
+       case 2 ... 8:
+               shift = 1;
+               for (i = 0; i < src_cnt; i++) {
+                       u_desc_ctrl.value |= (1 << shift);
+                       shift += 3;
+               }
+
+               if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
+                       u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
+       }
+
+       u_desc_ctrl.field.dest_write_en = 1;
+       u_desc_ctrl.field.blk1_cmd_ctrl = 0x7; /* direct fill */
+       u_desc_ctrl.field.int_en = int_en;
+       hw_desc->desc_ctrl = u_desc_ctrl.value;
+
+       return u_desc_ctrl.value;
+}
+
+static inline void
+iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+       iop3xx_desc_init_xor(desc->hw_desc, src_cnt, int_en);
+}
+
+/* return the number of operations */
+static inline int
+iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+       int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+       struct iop3xx_desc_aau *hw_desc, *prev_hw_desc, *iter;
+       union {
+               u32 value;
+               struct iop3xx_aau_desc_ctrl field;
+       } u_desc_ctrl;
+       int i, j;
+
+       hw_desc = desc->hw_desc;
+
+       for (i = 0, j = 0; (slot_cnt -= slots_per_op) >= 0;
+               i += slots_per_op, j++) {
+               iter = iop_hw_desc_slot_idx(hw_desc, i);
+               u_desc_ctrl.value = iop3xx_desc_init_xor(iter, src_cnt, int_en);
+               u_desc_ctrl.field.dest_write_en = 0;
+               u_desc_ctrl.field.zero_result_en = 1;
+               u_desc_ctrl.field.int_en = int_en;
+               iter->desc_ctrl = u_desc_ctrl.value;
+
+               /* for the subsequent descriptors preserve the store queue
+                * and chain them together
+                */
+               if (i) {
+                       prev_hw_desc =
+                               iop_hw_desc_slot_idx(hw_desc, i - slots_per_op);
+                       prev_hw_desc->next_desc =
+                               (u32) (desc->async_tx.phys + (i << 5));
+               }
+       }
+
+       return j;
+}
+
+static inline void
+iop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+       struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+       union {
+               u32 value;
+               struct iop3xx_aau_desc_ctrl field;
+       } u_desc_ctrl;
+
+       u_desc_ctrl.value = 0;
+       switch (src_cnt) {
+       case 25 ... 32:
+               u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+               hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+               /* fall through */
+       case 17 ... 24:
+               if (!u_desc_ctrl.field.blk_ctrl) {
+                       hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+                       u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+               }
+               hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = 0;
+               /* fall through */
+       case 9 ... 16:
+               if (!u_desc_ctrl.field.blk_ctrl)
+                       u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
+               hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = 0;
+               /* fall through */
+       case 1 ... 8:
+               if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
+                       u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
+       }
+
+       u_desc_ctrl.field.dest_write_en = 0;
+       u_desc_ctrl.field.int_en = int_en;
+       hw_desc->desc_ctrl = u_desc_ctrl.value;
+}
+
+static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
+                                       struct iop_adma_chan *chan,
+                                       u32 byte_count)
+{
+       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+       switch (chan->device->id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               hw_desc.dma->byte_count = byte_count;
+               break;
+       case AAU_ID:
+               hw_desc.aau->byte_count = byte_count;
+               break;
+       default:
+               BUG();
+       }
+}
+
+static inline void
+iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
+                       struct iop_adma_chan *chan)
+{
+       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+       switch (chan->device->id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               iop_desc_init_memcpy(desc, 1);
+               hw_desc.dma->byte_count = 0;
+               hw_desc.dma->dest_addr = 0;
+               hw_desc.dma->src_addr = 0;
+               break;
+       case AAU_ID:
+               iop_desc_init_null_xor(desc, 2, 1);
+               hw_desc.aau->byte_count = 0;
+               hw_desc.aau->dest_addr = 0;
+               hw_desc.aau->src[0] = 0;
+               hw_desc.aau->src[1] = 0;
+               break;
+       default:
+               BUG();
+       }
+}
+
+static inline void
+iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
+{
+       int slots_per_op = desc->slots_per_op;
+       struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+       int i = 0;
+
+       if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+               hw_desc->byte_count = len;
+       } else {
+               do {
+                       iter = iop_hw_desc_slot_idx(hw_desc, i);
+                       iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+                       len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+                       i += slots_per_op;
+               } while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
+
+               if (len) {
+                       iter = iop_hw_desc_slot_idx(hw_desc, i);
+                       iter->byte_count = len;
+               }
+       }
+}
+
+static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
+                                       struct iop_adma_chan *chan,
+                                       dma_addr_t addr)
+{
+       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+       switch (chan->device->id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               hw_desc.dma->dest_addr = addr;
+               break;
+       case AAU_ID:
+               hw_desc.aau->dest_addr = addr;
+               break;
+       default:
+               BUG();
+       }
+}
+
+static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
+                                       dma_addr_t addr)
+{
+       struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
+       hw_desc->src_addr = addr;
+}
+
+static inline void
+iop_desc_set_zero_sum_src_addr(struct iop_adma_desc_slot *desc, int src_idx,
+                               dma_addr_t addr)
+{
+
+       struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+       int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+       int i;
+
+       for (i = 0; (slot_cnt -= slots_per_op) >= 0;
+               i += slots_per_op, addr += IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+               iter = iop_hw_desc_slot_idx(hw_desc, i);
+               iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
+       }
+}
+
+static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
+                                       int src_idx, dma_addr_t addr)
+{
+
+       struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+       int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+       int i;
+
+       for (i = 0; (slot_cnt -= slots_per_op) >= 0;
+               i += slots_per_op, addr += IOP_ADMA_XOR_MAX_BYTE_COUNT) {
+               iter = iop_hw_desc_slot_idx(hw_desc, i);
+               iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
+       }
+}
+
+static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
+                                       u32 next_desc_addr)
+{
+       /* hw_desc->next_desc is the same location for all channels */
+       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+       BUG_ON(hw_desc.dma->next_desc);
+       hw_desc.dma->next_desc = next_desc_addr;
+}
+
+static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
+{
+       /* hw_desc->next_desc is the same location for all channels */
+       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+       return hw_desc.dma->next_desc;
+}
+
+static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
+{
+       /* hw_desc->next_desc is the same location for all channels */
+       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+       hw_desc.dma->next_desc = 0;
+}
+
+static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
+                                               u32 val)
+{
+       struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+       hw_desc->src[0] = val;
+}
+
+static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
+{
+       struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+       struct iop3xx_aau_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
+
+       BUG_ON(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en));
+       return desc_ctrl.zero_result_err;
+}
+
+static inline void iop_chan_append(struct iop_adma_chan *chan)
+{
+       u32 dma_chan_ctrl;
+       /* workaround dropped interrupts on 3xx */
+       mod_timer(&chan->cleanup_watchdog, jiffies + msecs_to_jiffies(3));
+
+       dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+       dma_chan_ctrl |= 0x2;
+       __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+}
+
+static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
+{
+       if (!busy)
+               del_timer(&chan->cleanup_watchdog);
+}
+
+static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+{
+       return __raw_readl(DMA_CSR(chan));
+}
+
+static inline void iop_chan_disable(struct iop_adma_chan *chan)
+{
+       u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+       dma_chan_ctrl &= ~1;
+       __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+}
+
+static inline void iop_chan_enable(struct iop_adma_chan *chan)
+{
+       u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+
+       dma_chan_ctrl |= 1;
+       __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+}
+
+static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
+{
+       u32 status = __raw_readl(DMA_CSR(chan));
+       status &= (1 << 9);
+       __raw_writel(status, DMA_CSR(chan));
+}
+
+static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
+{
+       u32 status = __raw_readl(DMA_CSR(chan));
+       status &= (1 << 8);
+       __raw_writel(status, DMA_CSR(chan));
+}
+
+static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
+{
+       u32 status = __raw_readl(DMA_CSR(chan));
+
+       switch (chan->device->id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               status &= (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1);
+               break;
+       case AAU_ID:
+               status &= (1 << 5);
+               break;
+       default:
+               BUG();
+       }
+
+       __raw_writel(status, DMA_CSR(chan));
+}
+
+static inline int
+iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
+{
+       return 0;
+}
+
+static inline int
+iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
+{
+       return 0;
+}
+
+static inline int
+iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+       return 0;
+}
+
+static inline int
+iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+       return test_bit(5, &status);
+}
+
+static inline int
+iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+       switch (chan->device->id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               return test_bit(2, &status);
+       default:
+               return 0;
+       }
+}
+
+static inline int
+iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+       switch (chan->device->id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               return test_bit(3, &status);
+       default:
+               return 0;
+       }
+}
+
+static inline int
+iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
+{
+       switch (chan->device->id) {
+       case DMA0_ID:
+       case DMA1_ID:
+               return test_bit(1, &status);
+       default:
+               return 0;
+       }
+}
+#endif /* _ADMA_H */
index 63feceb7ede558afe103496036f46cfb7195924b..81ca5d3e2bff4581759c6fdd604c8d4897f432eb 100644 (file)
@@ -144,24 +144,9 @@ extern int init_atu;
 #define IOP3XX_IAR             (volatile u32 *)IOP3XX_REG_ADDR(0x0380)
 
 /* DMA Controller  */
-#define IOP3XX_DMA0_CCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0400)
-#define IOP3XX_DMA0_CSR                (volatile u32 *)IOP3XX_REG_ADDR(0x0404)
-#define IOP3XX_DMA0_DAR                (volatile u32 *)IOP3XX_REG_ADDR(0x040c)
-#define IOP3XX_DMA0_NDAR       (volatile u32 *)IOP3XX_REG_ADDR(0x0410)
-#define IOP3XX_DMA0_PADR       (volatile u32 *)IOP3XX_REG_ADDR(0x0414)
-#define IOP3XX_DMA0_PUADR      (volatile u32 *)IOP3XX_REG_ADDR(0x0418)
-#define IOP3XX_DMA0_LADR       (volatile u32 *)IOP3XX_REG_ADDR(0x041c)
-#define IOP3XX_DMA0_BCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0420)
-#define IOP3XX_DMA0_DCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0424)
-#define IOP3XX_DMA1_CCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0440)
-#define IOP3XX_DMA1_CSR                (volatile u32 *)IOP3XX_REG_ADDR(0x0444)
-#define IOP3XX_DMA1_DAR                (volatile u32 *)IOP3XX_REG_ADDR(0x044c)
-#define IOP3XX_DMA1_NDAR       (volatile u32 *)IOP3XX_REG_ADDR(0x0450)
-#define IOP3XX_DMA1_PADR       (volatile u32 *)IOP3XX_REG_ADDR(0x0454)
-#define IOP3XX_DMA1_PUADR      (volatile u32 *)IOP3XX_REG_ADDR(0x0458)
-#define IOP3XX_DMA1_LADR       (volatile u32 *)IOP3XX_REG_ADDR(0x045c)
-#define IOP3XX_DMA1_BCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0460)
-#define IOP3XX_DMA1_DCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0464)
+#define IOP3XX_DMA_PHYS_BASE(chan) (IOP3XX_PERIPHERAL_PHYS_BASE + \
+                                       (0x400 + (chan << 6)))
+#define IOP3XX_DMA_UPPER_PA(chan)  (IOP3XX_DMA_PHYS_BASE(chan) + 0x27)
 
 /* Peripheral bus interface  */
 #define IOP3XX_PBCR            (volatile u32 *)IOP3XX_REG_ADDR(0x0680)
@@ -210,48 +195,8 @@ extern int init_atu;
 #define IOP_TMR_RATIO_1_1  0x00
 
 /* Application accelerator unit  */
-#define IOP3XX_AAU_ACR         (volatile u32 *)IOP3XX_REG_ADDR(0x0800)
-#define IOP3XX_AAU_ASR         (volatile u32 *)IOP3XX_REG_ADDR(0x0804)
-#define IOP3XX_AAU_ADAR                (volatile u32 *)IOP3XX_REG_ADDR(0x0808)
-#define IOP3XX_AAU_ANDAR       (volatile u32 *)IOP3XX_REG_ADDR(0x080c)
-#define IOP3XX_AAU_SAR1                (volatile u32 *)IOP3XX_REG_ADDR(0x0810)
-#define IOP3XX_AAU_SAR2                (volatile u32 *)IOP3XX_REG_ADDR(0x0814)
-#define IOP3XX_AAU_SAR3                (volatile u32 *)IOP3XX_REG_ADDR(0x0818)
-#define IOP3XX_AAU_SAR4                (volatile u32 *)IOP3XX_REG_ADDR(0x081c)
-#define IOP3XX_AAU_DAR         (volatile u32 *)IOP3XX_REG_ADDR(0x0820)
-#define IOP3XX_AAU_ABCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0824)
-#define IOP3XX_AAU_ADCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0828)
-#define IOP3XX_AAU_SAR5                (volatile u32 *)IOP3XX_REG_ADDR(0x082c)
-#define IOP3XX_AAU_SAR6                (volatile u32 *)IOP3XX_REG_ADDR(0x0830)
-#define IOP3XX_AAU_SAR7                (volatile u32 *)IOP3XX_REG_ADDR(0x0834)
-#define IOP3XX_AAU_SAR8                (volatile u32 *)IOP3XX_REG_ADDR(0x0838)
-#define IOP3XX_AAU_EDCR0       (volatile u32 *)IOP3XX_REG_ADDR(0x083c)
-#define IOP3XX_AAU_SAR9                (volatile u32 *)IOP3XX_REG_ADDR(0x0840)
-#define IOP3XX_AAU_SAR10       (volatile u32 *)IOP3XX_REG_ADDR(0x0844)
-#define IOP3XX_AAU_SAR11       (volatile u32 *)IOP3XX_REG_ADDR(0x0848)
-#define IOP3XX_AAU_SAR12       (volatile u32 *)IOP3XX_REG_ADDR(0x084c)
-#define IOP3XX_AAU_SAR13       (volatile u32 *)IOP3XX_REG_ADDR(0x0850)
-#define IOP3XX_AAU_SAR14       (volatile u32 *)IOP3XX_REG_ADDR(0x0854)
-#define IOP3XX_AAU_SAR15       (volatile u32 *)IOP3XX_REG_ADDR(0x0858)
-#define IOP3XX_AAU_SAR16       (volatile u32 *)IOP3XX_REG_ADDR(0x085c)
-#define IOP3XX_AAU_EDCR1       (volatile u32 *)IOP3XX_REG_ADDR(0x0860)
-#define IOP3XX_AAU_SAR17       (volatile u32 *)IOP3XX_REG_ADDR(0x0864)
-#define IOP3XX_AAU_SAR18       (volatile u32 *)IOP3XX_REG_ADDR(0x0868)
-#define IOP3XX_AAU_SAR19       (volatile u32 *)IOP3XX_REG_ADDR(0x086c)
-#define IOP3XX_AAU_SAR20       (volatile u32 *)IOP3XX_REG_ADDR(0x0870)
-#define IOP3XX_AAU_SAR21       (volatile u32 *)IOP3XX_REG_ADDR(0x0874)
-#define IOP3XX_AAU_SAR22       (volatile u32 *)IOP3XX_REG_ADDR(0x0878)
-#define IOP3XX_AAU_SAR23       (volatile u32 *)IOP3XX_REG_ADDR(0x087c)
-#define IOP3XX_AAU_SAR24       (volatile u32 *)IOP3XX_REG_ADDR(0x0880)
-#define IOP3XX_AAU_EDCR2       (volatile u32 *)IOP3XX_REG_ADDR(0x0884)
-#define IOP3XX_AAU_SAR25       (volatile u32 *)IOP3XX_REG_ADDR(0x0888)
-#define IOP3XX_AAU_SAR26       (volatile u32 *)IOP3XX_REG_ADDR(0x088c)
-#define IOP3XX_AAU_SAR27       (volatile u32 *)IOP3XX_REG_ADDR(0x0890)
-#define IOP3XX_AAU_SAR28       (volatile u32 *)IOP3XX_REG_ADDR(0x0894)
-#define IOP3XX_AAU_SAR29       (volatile u32 *)IOP3XX_REG_ADDR(0x0898)
-#define IOP3XX_AAU_SAR30       (volatile u32 *)IOP3XX_REG_ADDR(0x089c)
-#define IOP3XX_AAU_SAR31       (volatile u32 *)IOP3XX_REG_ADDR(0x08a0)
-#define IOP3XX_AAU_SAR32       (volatile u32 *)IOP3XX_REG_ADDR(0x08a4)
+#define IOP3XX_AAU_PHYS_BASE (IOP3XX_PERIPHERAL_PHYS_BASE + 0x800)
+#define IOP3XX_AAU_UPPER_PA (IOP3XX_AAU_PHYS_BASE + 0xa7)
 
 /* I2C bus interface unit  */
 #define IOP3XX_ICR0            (volatile u32 *)IOP3XX_REG_ADDR(0x1680)
@@ -329,6 +274,9 @@ static inline void write_tisr(u32 val)
        asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (val));
 }
 
+extern struct platform_device iop3xx_dma_0_channel;
+extern struct platform_device iop3xx_dma_1_channel;
+extern struct platform_device iop3xx_aau_channel;
 extern struct platform_device iop3xx_i2c0_device;
 extern struct platform_device iop3xx_i2c1_device;
 
diff --git a/include/asm-arm/hardware/iop_adma.h b/include/asm-arm/hardware/iop_adma.h
new file mode 100644 (file)
index 0000000..ca8e71f
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright Â© 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef IOP_ADMA_H
+#define IOP_ADMA_H
+#include <linux/types.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+
+#define IOP_ADMA_SLOT_SIZE 32
+#define IOP_ADMA_THRESHOLD 4
+
+/**
+ * struct iop_adma_device - internal representation of an ADMA device
+ * @pdev: Platform device
+ * @id: HW ADMA Device selector
+ * @dma_desc_pool: base of DMA descriptor region (DMA address)
+ * @dma_desc_pool_virt: base of DMA descriptor region (CPU address)
+ * @common: embedded struct dma_device
+ */
+struct iop_adma_device {
+       struct platform_device *pdev;
+       int id;
+       dma_addr_t dma_desc_pool;
+       void *dma_desc_pool_virt;
+       struct dma_device common;
+};
+
+/**
+ * struct iop_adma_chan - internal representation of an ADMA device
+ * @pending: allows batching of hardware operations
+ * @completed_cookie: identifier for the most recently completed operation
+ * @lock: serializes enqueue/dequeue operations to the slot pool
+ * @mmr_base: memory mapped register base
+ * @chain: device chain view of the descriptors
+ * @device: parent device
+ * @common: common dmaengine channel object members
+ * @last_used: place holder for allocation to continue from where it left off
+ * @all_slots: complete domain of slots usable by the channel
+ * @cleanup_watchdog: workaround missed interrupts on iop3xx
+ * @slots_allocated: records the actual size of the descriptor slot pool
+ * @irq_tasklet: bottom half where iop_adma_slot_cleanup runs
+ */
+struct iop_adma_chan {
+       int pending;
+       dma_cookie_t completed_cookie;
+       spinlock_t lock; /* protects the descriptor slot pool */
+       void __iomem *mmr_base;
+       struct list_head chain;
+       struct iop_adma_device *device;
+       struct dma_chan common;
+       struct iop_adma_desc_slot *last_used;
+       struct list_head all_slots;
+       struct timer_list cleanup_watchdog;
+       int slots_allocated;
+       struct tasklet_struct irq_tasklet;
+};
+
+/**
+ * struct iop_adma_desc_slot - IOP-ADMA software descriptor
+ * @slot_node: node on the iop_adma_chan.all_slots list
+ * @chain_node: node on the op_adma_chan.chain list
+ * @hw_desc: virtual address of the hardware descriptor chain
+ * @phys: hardware address of the hardware descriptor chain
+ * @group_head: first operation in a transaction
+ * @slot_cnt: total slots used in an transaction (group of operations)
+ * @slots_per_op: number of slots per operation
+ * @idx: pool index
+ * @unmap_src_cnt: number of xor sources
+ * @unmap_len: transaction bytecount
+ * @async_tx: support for the async_tx api
+ * @group_list: list of slots that make up a multi-descriptor transaction
+ *     for example transfer lengths larger than the supported hw max
+ * @xor_check_result: result of zero sum
+ * @crc32_result: result crc calculation
+ */
+struct iop_adma_desc_slot {
+       struct list_head slot_node;
+       struct list_head chain_node;
+       void *hw_desc;
+       struct iop_adma_desc_slot *group_head;
+       u16 slot_cnt;
+       u16 slots_per_op;
+       u16 idx;
+       u16 unmap_src_cnt;
+       size_t unmap_len;
+       struct dma_async_tx_descriptor async_tx;
+       union {
+               u32 *xor_check_result;
+               u32 *crc32_result;
+       };
+};
+
+struct iop_adma_platform_data {
+       int hw_id;
+       dma_cap_mask_t cap_mask;
+       size_t pool_size;
+};
+
+#define to_iop_sw_desc(addr_hw_desc) \
+       container_of(addr_hw_desc, struct iop_adma_desc_slot, hw_desc)
+#define iop_hw_desc_slot_idx(hw_desc, idx) \
+       ( (void *) (((unsigned long) hw_desc) + ((idx) << 5)) )
+#endif
diff --git a/include/asm-arm/hwcap.h b/include/asm-arm/hwcap.h
new file mode 100644 (file)
index 0000000..01a1391
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __ASMARM_HWCAP_H
+#define __ASMARM_HWCAP_H
+
+/*
+ * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
+ */
+#define HWCAP_SWP      1
+#define HWCAP_HALF     2
+#define HWCAP_THUMB    4
+#define HWCAP_26BIT    8       /* Play it safe */
+#define HWCAP_FAST_MULT        16
+#define HWCAP_FPA      32
+#define HWCAP_VFP      64
+#define HWCAP_EDSP     128
+#define HWCAP_JAVA     256
+#define HWCAP_IWMMXT   512
+#define HWCAP_CRUNCH   1024
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP      (elf_hwcap)
+extern unsigned int elf_hwcap;
+#endif
+
+#endif
index f21abd4ddac61b8915fb6c437d45378c48b38b0f..ed3f898191f4d4b0eeb347a3e47df5966b23c186 100644 (file)
@@ -25,11 +25,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
  */
 #define PCI_DMA_BUS_IS_PHYS     (0)
 
-/*
- * We don't support DAC DMA cycles.
- */
-#define pci_dac_dma_supported(pci_dev, mask)   (0)
-
 /*
  * Whether pci_unmap_{single,page} is a nop depends upon the
  * configuration.
@@ -76,10 +71,6 @@ pcibios_select_root(struct pci_dev *pdev, struct resource *res)
        return root;
 }
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
  
 #endif
index ee3d93c281d809900cd13086932755a368f18e40..7aaa206cb54ef22e8a45d92822b31bc8bda18782 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef __ASM_ARM_PTRACE_H
 #define __ASM_ARM_PTRACE_H
 
+#include <asm/hwcap.h>
+
 #define PTRACE_GETREGS         12
 #define PTRACE_SETREGS         13
 #define PTRACE_GETFPREGS       14
@@ -45,6 +47,7 @@
 #define PSR_T_BIT      0x00000020
 #define PSR_F_BIT      0x00000040
 #define PSR_I_BIT      0x00000080
+#define PSR_A_BIT      0x00000100
 #define PSR_J_BIT      0x01000000
 #define PSR_Q_BIT      0x08000000
 #define PSR_V_BIT      0x10000000
@@ -103,6 +106,10 @@ struct pt_regs {
 #define thumb_mode(regs) (0)
 #endif
 
+#define isa_mode(regs) \
+       ((((regs)->ARM_cpsr & PSR_J_BIT) >> 23) | \
+        (((regs)->ARM_cpsr & PSR_T_BIT) >> 5))
+
 #define processor_mode(regs) \
        ((regs)->ARM_cpsr & MODE_MASK)
 
@@ -117,14 +124,17 @@ struct pt_regs {
  */
 static inline int valid_user_regs(struct pt_regs *regs)
 {
-       if (user_mode(regs) &&
-           (regs->ARM_cpsr & (PSR_F_BIT|PSR_I_BIT)) == 0)
+       if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) {
+               regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT);
                return 1;
+       }
 
        /*
         * Force CPSR to something logical...
         */
-       regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT;
+       regs->ARM_cpsr &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | PSR_T_BIT | MODE32_BIT;
+       if (!(elf_hwcap & HWCAP_26BIT))
+               regs->ARM_cpsr |= USR_MODE;
 
        return 0;
 }
index c68e1680da0173d5754d1a1df4944120a5239e58..71f8fe7832581b41a60014ba2895e1d9c5cfff10 100644 (file)
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+header-y += fixed_code.h
index 57f37ccdcdf1db421f25921c8db7bbdc34274671..c4d6cbbf96d490283df0a12fb6375f63f16a16b1 100644 (file)
@@ -67,6 +67,18 @@ extern void evt14_softirq(void);
 extern asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs);
 extern void bfin_gpio_interrupt_setup(int irq, int irq_pfx, int type);
 
+extern asmlinkage void finish_atomic_sections (struct pt_regs *regs);
+extern char fixed_code_start;
+extern char fixed_code_end;
+extern int atomic_xchg32(void);
+extern int atomic_cas32(void);
+extern int atomic_add32(void);
+extern int atomic_sub32(void);
+extern int atomic_ior32(void);
+extern int atomic_and32(void);
+extern int atomic_xor32(void);
+extern void sigreturn_stub(void);
+
 extern void *l1_data_A_sram_alloc(size_t);
 extern void *l1_data_B_sram_alloc(size_t);
 extern void *l1_inst_sram_alloc(size_t);
index 3bad2d1e6a8cd87da60bf12a0a4ef122d62714ea..bec6ecdf1bdbc5cd23a5421c28f194132fbaa9f6 100644 (file)
@@ -57,8 +57,8 @@ struct cplb_tab {
        u16 size;
 };
 
-u_long icplb_table[MAX_CPLBS+1];
-u_long dcplb_table[MAX_CPLBS+1];
+extern u_long icplb_table[MAX_CPLBS+1];
+extern u_long dcplb_table[MAX_CPLBS+1];
 
 /* Till here we are discussing about the static memory management model.
  * However, the operating envoronments commonly define more CPLB
@@ -70,134 +70,27 @@ u_long dcplb_table[MAX_CPLBS+1];
  */
 
 #ifdef CONFIG_CPLB_SWITCH_TAB_L1
-u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data));
-u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data));
+extern u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data));
+extern u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data));
 
 #ifdef CONFIG_CPLB_INFO
-u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data));
-u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data));
+extern u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data));
+extern u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data));
 #endif /* CONFIG_CPLB_INFO */
 
 #else
 
-u_long ipdt_table[MAX_SWITCH_I_CPLBS+1];
-u_long dpdt_table[MAX_SWITCH_D_CPLBS+1];
+extern u_long ipdt_table[MAX_SWITCH_I_CPLBS+1];
+extern u_long dpdt_table[MAX_SWITCH_D_CPLBS+1];
 
 #ifdef CONFIG_CPLB_INFO
-u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS];
-u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS];
+extern u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS];
+extern u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS];
 #endif /* CONFIG_CPLB_INFO */
 
 #endif /*CONFIG_CPLB_SWITCH_TAB_L1*/
 
-struct s_cplb {
-       struct cplb_tab init_i;
-       struct cplb_tab init_d;
-       struct cplb_tab switch_i;
-       struct cplb_tab switch_d;
-};
+extern unsigned long reserved_mem_dcache_on;
+extern unsigned long reserved_mem_icache_on;
 
-#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
-static struct cplb_desc cplb_data[] = {
-       {
-               .start = 0,
-               .end = SIZE_4K,
-               .psize = SIZE_4K,
-               .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
-               .i_conf = SDRAM_OOPS,
-               .d_conf = SDRAM_OOPS,
-#if defined(CONFIG_DEBUG_HUNT_FOR_ZERO)
-               .valid = 1,
-#else
-               .valid = 0,
-#endif
-               .name = "ZERO Pointer Saveguard",
-       },
-       {
-               .start = L1_CODE_START,
-               .end = L1_CODE_START + L1_CODE_LENGTH,
-               .psize = SIZE_4M,
-               .attr = INITIAL_T | SWITCH_T | I_CPLB,
-               .i_conf = L1_IMEMORY,
-               .d_conf = 0,
-               .valid = 1,
-               .name = "L1 I-Memory",
-       },
-       {
-               .start = L1_DATA_A_START,
-               .end = L1_DATA_B_START + L1_DATA_B_LENGTH,
-               .psize = SIZE_4M,
-               .attr = INITIAL_T | SWITCH_T | D_CPLB,
-               .i_conf = 0,
-               .d_conf = L1_DMEMORY,
-#if ((L1_DATA_A_LENGTH > 0) || (L1_DATA_B_LENGTH > 0))
-               .valid = 1,
-#else
-               .valid = 0,
-#endif
-               .name = "L1 D-Memory",
-       },
-       {
-               .start = 0,
-               .end = 0,  /* dynamic */
-               .psize = 0,
-               .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
-               .i_conf =  SDRAM_IGENERIC,
-               .d_conf =  SDRAM_DGENERIC,
-               .valid = 1,
-               .name = "SDRAM Kernel",
-       },
-       {
-               .start = 0, /* dynamic */
-               .end = 0, /* dynamic */
-               .psize = 0,
-               .attr = INITIAL_T | SWITCH_T | D_CPLB,
-               .i_conf =  SDRAM_IGENERIC,
-               .d_conf =  SDRAM_DNON_CHBL,
-               .valid = 1,
-               .name = "SDRAM RAM MTD",
-       },
-       {
-               .start = 0, /* dynamic */
-               .end = 0,   /* dynamic */
-               .psize = SIZE_1M,
-               .attr = INITIAL_T | SWITCH_T | D_CPLB,
-               .d_conf = SDRAM_DNON_CHBL,
-               .valid = 1,//(DMA_UNCACHED_REGION > 0),
-               .name = "SDRAM Uncached DMA ZONE",
-       },
-       {
-               .start = 0, /* dynamic */
-               .end = 0, /* dynamic */
-               .psize = 0,
-               .attr = SWITCH_T | D_CPLB,
-               .i_conf = 0, /* dynamic */
-               .d_conf = 0, /* dynamic */
-               .valid = 1,
-               .name = "SDRAM Reserved Memory",
-       },
-       {
-               .start = ASYNC_BANK0_BASE,
-               .end = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE,
-               .psize = 0,
-               .attr = SWITCH_T | D_CPLB,
-               .d_conf = SDRAM_EBIU,
-               .valid = 1,
-               .name = "ASYNC Memory",
-       },
-       {
-#if defined(CONFIG_BF561)
-               .start = L2_SRAM,
-               .end = L2_SRAM_END,
-               .psize = SIZE_1M,
-               .attr = SWITCH_T | D_CPLB,
-               .i_conf = L2_MEMORY,
-               .d_conf = L2_MEMORY,
-               .valid = 1,
-#else
-               .valid = 0,
-#endif
-               .name = "L2 Memory",
-       }
-};
-#endif
+extern void generate_cpl_tables(void);
diff --git a/include/asm-blackfin/fixed_code.h b/include/asm-blackfin/fixed_code.h
new file mode 100644 (file)
index 0000000..e6df84e
--- /dev/null
@@ -0,0 +1,20 @@
+/* This file defines the fixed addresses where userspace programs can find
+   atomic code sequences.  */
+
+#define FIXED_CODE_START       0x400
+
+#define SIGRETURN_STUB         0x400
+
+#define ATOMIC_SEQS_START      0x410
+
+#define ATOMIC_XCHG32          0x410
+#define ATOMIC_CAS32           0x420
+#define ATOMIC_ADD32           0x430
+#define ATOMIC_SUB32           0x440
+#define ATOMIC_IOR32           0x450
+#define ATOMIC_AND32           0x460
+#define ATOMIC_XOR32           0x470
+
+#define ATOMIC_SEQS_END                0x480
+
+#define FIXED_CODE_END         0x480
index d98d77ad71f76ac48a1525eeb1f9c668cbb7d6eb..7480cfa7e2d64304c58ff924b05fbfc385ad8bf6 100644 (file)
 
 #endif
 
+#ifdef BF548_FAMILY
+#include <asm-blackfin/mach-bf548/gpio.h>
+#endif
+
 #ifdef BF561_FAMILY
 #define MAX_BLACKFIN_GPIOS 48
+
+#define        GPIO_PF0        0
+#define        GPIO_PF1        1
+#define        GPIO_PF2        2
+#define        GPIO_PF3        3
+#define        GPIO_PF4        4
+#define        GPIO_PF5        5
+#define        GPIO_PF6        6
+#define        GPIO_PF7        7
+#define        GPIO_PF8        8
+#define        GPIO_PF9        9
+#define        GPIO_PF10       10
+#define        GPIO_PF11       11
+#define        GPIO_PF12       12
+#define        GPIO_PF13       13
+#define        GPIO_PF14       14
+#define        GPIO_PF15       15
+#define        GPIO_PF16       16
+#define        GPIO_PF17       17
+#define        GPIO_PF18       18
+#define        GPIO_PF19       19
+#define        GPIO_PF20       20
+#define        GPIO_PF21       21
+#define        GPIO_PF22       22
+#define        GPIO_PF23       23
+#define        GPIO_PF24       24
+#define        GPIO_PF25       25
+#define        GPIO_PF26       26
+#define        GPIO_PF27       27
+#define        GPIO_PF28       28
+#define        GPIO_PF29       29
+#define        GPIO_PF30       30
+#define        GPIO_PF31       31
+#define        GPIO_PF32       32
+#define        GPIO_PF33       33
+#define        GPIO_PF34       34
+#define        GPIO_PF35       35
+#define        GPIO_PF36       36
+#define        GPIO_PF37       37
+#define        GPIO_PF38       38
+#define        GPIO_PF39       39
+#define        GPIO_PF40       40
+#define        GPIO_PF41       41
+#define        GPIO_PF42       42
+#define        GPIO_PF43       43
+#define        GPIO_PF44       44
+#define        GPIO_PF45       45
+#define        GPIO_PF46       46
+#define        GPIO_PF47       47
+
 #define PORT_FIO0 GPIO_0
 #define PORT_FIO1 GPIO_16
 #define PORT_FIO2 GPIO_32
 * MODIFICATION HISTORY :
 **************************************************************/
 
+#ifndef BF548_FAMILY
 void set_gpio_dir(unsigned short, unsigned short);
 void set_gpio_inen(unsigned short, unsigned short);
 void set_gpio_polar(unsigned short, unsigned short);
@@ -299,6 +354,7 @@ struct gpio_port_t {
        unsigned short dummy16;
        unsigned short inen;
 };
+#endif
 
 #ifdef CONFIG_PM
 #define PM_WAKE_RISING 0x1
@@ -357,8 +413,10 @@ void gpio_free(unsigned short);
 void gpio_set_value(unsigned short gpio, unsigned short arg);
 unsigned short gpio_get_value(unsigned short gpio);
 
+#ifndef BF548_FAMILY
 #define gpio_get_value(gpio)           get_gpio_data(gpio)
 #define gpio_set_value(gpio, value)    set_gpio_data(gpio, value)
+#endif
 
 void gpio_direction_input(unsigned short gpio);
 void gpio_direction_output(unsigned short gpio);
index 0cab0d35badc42a7622ae816a058814097114b8e..b6b19f1b9dab56dc1aad604208ba960eea8567f0 100644 (file)
@@ -28,7 +28,11 @@ typedef struct {
  * SOFTIRQ_MASK: 0x00ff0000
  */
 
+#if NR_IRQS > 256
+#define HARDIRQ_BITS   9
+#else
 #define HARDIRQ_BITS   8
+#endif
 
 #ifdef NR_IRQS
 # if (1 << HARDIRQ_BITS) < NR_IRQS
diff --git a/include/asm-blackfin/kgdb.h b/include/asm-blackfin/kgdb.h
new file mode 100644 (file)
index 0000000..532bd90
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * File:         include/asm-blackfin/kgdb.h
+ * Based on:
+ * Author:       Sonic Zhang
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:          $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $
+ *
+ * Modified:
+ *               Copyright 2005-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
+ */
+
+#ifndef __ASM_BLACKFIN_KGDB_H__
+#define __ASM_BLACKFIN_KGDB_H__
+
+#include <linux/ptrace.h>
+
+/* gdb locks */
+#define KGDB_MAX_NO_CPUS 8
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+/* Longer buffer is needed to list all threads */
+#define BUFMAX 2048
+
+/*
+ *  Note that this register image is different from
+ *  the register image that Linux produces at interrupt time.
+ *  
+ *  Linux's register image is defined by struct pt_regs in ptrace.h.
+ */
+enum regnames {
+  /* Core Registers */
+  BFIN_R0 = 0,
+  BFIN_R1,
+  BFIN_R2,
+  BFIN_R3,
+  BFIN_R4,
+  BFIN_R5,
+  BFIN_R6,
+  BFIN_R7,
+  BFIN_P0,
+  BFIN_P1,
+  BFIN_P2,
+  BFIN_P3,
+  BFIN_P4,
+  BFIN_P5,
+  BFIN_SP,
+  BFIN_FP,
+  BFIN_I0,
+  BFIN_I1,
+  BFIN_I2,
+  BFIN_I3,
+  BFIN_M0,
+  BFIN_M1,
+  BFIN_M2,
+  BFIN_M3,
+  BFIN_B0,
+  BFIN_B1,
+  BFIN_B2,
+  BFIN_B3,
+  BFIN_L0,
+  BFIN_L1,
+  BFIN_L2,
+  BFIN_L3,
+  BFIN_A0_DOT_X,
+  BFIN_A0_DOT_W,
+  BFIN_A1_DOT_X,
+  BFIN_A1_DOT_W,
+  BFIN_ASTAT,
+  BFIN_RETS,
+  BFIN_LC0,
+  BFIN_LT0,
+  BFIN_LB0,
+  BFIN_LC1,
+  BFIN_LT1,
+  BFIN_LB1,
+  BFIN_CYCLES,
+  BFIN_CYCLES2,
+  BFIN_USP,
+  BFIN_SEQSTAT,
+  BFIN_SYSCFG,
+  BFIN_RETI,
+  BFIN_RETX,
+  BFIN_RETN,
+  BFIN_RETE,
+  
+  /* Pseudo Registers */
+  BFIN_PC,
+  BFIN_CC,
+  BFIN_EXTRA1,         /* Address of .text section.  */
+  BFIN_EXTRA2,         /* Address of .data section.  */
+  BFIN_EXTRA3,         /* Address of .bss section.  */
+  BFIN_FDPIC_EXEC, 
+  BFIN_FDPIC_INTERP,
+
+  /* MMRs */
+  BFIN_IPEND,
+
+  /* LAST ENTRY SHOULD NOT BE CHANGED.  */
+  BFIN_NUM_REGS                /* The number of all registers.  */
+};
+
+/* Number of bytes of registers.  */
+#define NUMREGBYTES BFIN_NUM_REGS*4
+
+#define BREAKPOINT() asm("   EXCPT 2;");
+#define BREAK_INSTR_SIZE       2
+#define HW_BREAKPOINT_NUM              6
+
+/* Instruction watchpoint address control register bits mask */
+#define WPPWR          0x1
+#define WPIREN01       0x2
+#define WPIRINV01      0x4
+#define WPIAEN0                0x8
+#define WPIAEN1                0x10
+#define WPICNTEN0      0x20
+#define WPICNTEN1      0x40
+#define EMUSW0         0x80
+#define EMUSW1         0x100
+#define WPIREN23       0x200
+#define WPIRINV23      0x400
+#define WPIAEN2                0x800
+#define WPIAEN3                0x1000
+#define WPICNTEN2      0x2000
+#define WPICNTEN3      0x4000
+#define EMUSW2         0x8000
+#define EMUSW3         0x10000
+#define WPIREN45       0x20000
+#define WPIRINV45      0x40000
+#define WPIAEN4                0x80000
+#define WPIAEN5                0x100000
+#define WPICNTEN4      0x200000
+#define WPICNTEN5      0x400000
+#define EMUSW4         0x800000
+#define EMUSW5         0x1000000
+#define WPAND          0x2000000
+
+/* Data watchpoint address control register bits mask */
+#define WPDREN01       0x1
+#define WPDRINV01      0x2
+#define WPDAEN0                0x4
+#define WPDAEN1                0x8
+#define WPDCNTEN0      0x10
+#define WPDCNTEN1      0x20
+#define WPDSRC0                0xc0
+#define WPDACC0                0x300
+#define WPDSRC1                0xc00
+#define WPDACC1                0x3000
+
+/* Watchpoint status register bits mask */
+#define STATIA0                0x1
+#define STATIA1                0x2
+#define STATIA2                0x4
+#define STATIA3                0x8
+#define STATIA4                0x10
+#define STATIA5                0x20
+#define STATDA0                0x40
+#define STATDA1                0x80
+
+extern void kgdb_print(const char *fmt, ...);
+
+#endif
index bd9d5e94307d0ca7823ff50c88bf19d0f74c94f0..16c672c01d80cb490d2dc0fceff35ed6d67947f7 100644 (file)
@@ -51,4 +51,7 @@
 #define CH_MEM_STREAM1_DEST     10      /* TX */
 #define CH_MEM_STREAM1_SRC      11      /* RX */
 
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+
 #endif
diff --git a/include/asm-blackfin/mach-bf533/portmux.h b/include/asm-blackfin/mach-bf533/portmux.h
new file mode 100644 (file)
index 0000000..b88d7a0
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_PPI0_CLK     (P_DONTCARE)
+#define P_PPI0_FS1     (P_DONTCARE)
+#define P_PPI0_FS2     (P_DONTCARE)
+#define P_PPI0_FS3     (P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_PPI0_D15     (P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_PPI0_D14     (P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_PPI0_D13     (P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_PPI0_D12     (P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_PPI0_D11     (P_DEFINED | P_IDENT(GPIO_PF8))
+#define P_PPI0_D10     (P_DEFINED | P_IDENT(GPIO_PF9))
+#define P_PPI0_D9      (P_DEFINED | P_IDENT(GPIO_PF10))
+#define P_PPI0_D8      (P_DEFINED | P_IDENT(GPIO_PF11))
+#define P_PPI0_D0      (P_DONTCARE)
+#define P_PPI0_D1      (P_DONTCARE)
+#define P_PPI0_D2      (P_DONTCARE)
+#define P_PPI0_D3      (P_DONTCARE)
+#define P_PPI0_D4      (P_DEFINED | P_IDENT(GPIO_PF15))
+#define P_PPI0_D5      (P_DEFINED | P_IDENT(GPIO_PF14))
+#define P_PPI0_D6      (P_DEFINED | P_IDENT(GPIO_PF13))
+#define P_PPI0_D7      (P_DEFINED | P_IDENT(GPIO_PF12))
+
+#define P_SPORT1_TSCLK (P_DONTCARE)
+#define P_SPORT1_RSCLK (P_DONTCARE)
+#define P_SPORT0_TSCLK (P_DONTCARE)
+#define P_SPORT0_RSCLK (P_DONTCARE)
+#define P_UART0_RX     (P_DONTCARE)
+#define P_UART0_TX     (P_DONTCARE)
+#define P_SPORT1_DRSEC (P_DONTCARE)
+#define P_SPORT1_RFS   (P_DONTCARE)
+#define P_SPORT1_DTPRI (P_DONTCARE)
+#define P_SPORT1_DTSEC (P_DONTCARE)
+#define P_SPORT1_TFS   (P_DONTCARE)
+#define P_SPORT1_DRPRI (P_DONTCARE)
+#define P_SPORT0_DRSEC (P_DONTCARE)
+#define P_SPORT0_RFS   (P_DONTCARE)
+#define P_SPORT0_DTPRI (P_DONTCARE)
+#define P_SPORT0_DTSEC (P_DONTCARE)
+#define P_SPORT0_TFS   (P_DONTCARE)
+#define P_SPORT0_DRPRI (P_DONTCARE)
+
+#define P_SPI0_MOSI    (P_DONTCARE)
+#define P_SPI0_MIS0    (P_DONTCARE)
+#define P_SPI0_SCK     (P_DONTCARE)
+#define P_SPI0_SSEL7   (P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_SPI0_SSEL6   (P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_SPI0_SSEL5   (P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_SPI0_SSEL4   (P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_SPI0_SSEL3   (P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_SPI0_SSEL2   (P_DEFINED | P_IDENT(GPIO_PF2))
+#define P_SPI0_SSEL1   (P_DEFINED | P_IDENT(GPIO_PF1))
+#define P_SPI0_SS      (P_DEFINED | P_IDENT(GPIO_PF0))
+
+#define P_TMR2         (P_DONTCARE)
+#define P_TMR1         (P_DONTCARE)
+#define P_TMR0         (P_DONTCARE)
+#define P_TMRCLK       (P_DEFINED | P_IDENT(GPIO_PF1))
+
+
+
+
+
+#endif /* _MACH_PORTMUX_H_ */
index 7a964040870a047292f84678c3788dc2c2bff07f..021991984e6e7ce4f5ae7adc197396d954bf83ca 100644 (file)
@@ -52,4 +52,7 @@
 #define CH_MEM_STREAM1_DEST    14       /* TX */
 #define CH_MEM_STREAM1_SRC     15       /* RX */
 
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+
 #endif
diff --git a/include/asm-blackfin/mach-bf537/portmux.h b/include/asm-blackfin/mach-bf537/portmux.h
new file mode 100644 (file)
index 0000000..23e13c5
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_UART0_TX     (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(0))
+#define P_UART0_RX     (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(0))
+#define P_UART1_TX     (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(0))
+#define P_UART1_RX     (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(0))
+#define P_TMR5         (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(0))
+#define P_TMR4         (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(0))
+#define P_TMR3         (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(0))
+#define P_TMR2         (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(0))
+#define P_TMR1         (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(0))
+#define P_TMR0         (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(0))
+#define P_SPI0_SSEL1   (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(0))
+#define P_SPI0_MOSI    (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(0))
+#define P_SPI0_MISO    (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(0))
+#define P_SPI0_SCK     (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(0))
+#define P_SPI0_SS      (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(0))
+#define P_PPI0_CLK     (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(0))
+#define P_DMAR0                (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1))
+#define P_DMAR1                (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1))
+#define P_TMR7         (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1))
+#define P_TMR6         (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1))
+#define P_SPI0_SSEL6   (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1))
+#define P_SPI0_SSEL5   (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1))
+#define P_SPI0_SSEL4   (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1))
+#define P_PPI0_FS3     (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1))
+#define P_PPI0_FS2     (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1))
+#define P_PPI0_FS1     (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
+#define P_TACLK0       (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
+#define P_TMRCLK       (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+
+#define P_PPI0_D0      (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0))
+#define P_PPI0_D1      (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
+#define P_PPI0_D2      (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(0))
+#define P_PPI0_D3      (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0))
+#define P_PPI0_D4      (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(0))
+#define P_PPI0_D5      (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0))
+#define P_PPI0_D6      (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(0))
+#define P_PPI0_D7      (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(0))
+#define P_PPI0_D8      (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(0))
+#define P_PPI0_D9      (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(0))
+#define P_PPI0_D10     (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(0))
+#define P_PPI0_D11     (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(0))
+#define P_PPI0_D12     (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(0))
+#define P_PPI0_D13     (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0))
+#define P_PPI0_D14     (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0))
+#define P_PPI0_D15     (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0))
+#define P_SPORT1_DRSEC (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(1))
+#define P_SPORT1_DTSEC (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(1))
+#define P_SPORT1_RSCLK (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(1))
+#define P_SPORT1_RFS   (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(1))
+#define P_SPORT1_DRPRI (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(1))
+#define P_SPORT1_TSCLK (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(1))
+#define P_SPORT1_TFS   (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(1))
+#define P_SPORT1_DTPRI (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(1))
+
+#define P_MII0_ETxD0   (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(0))
+#define P_MII0_ETxD1   (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(0))
+#define P_MII0_ETxD2   (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(0))
+#define P_MII0_ETxD3   (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(0))
+#define P_MII0_ETxEN   (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(0))
+#define P_MII0_TxCLK   (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(0))
+#define P_MII0_PHYINT  (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(0))
+#define P_MII0_COL     (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(0))
+#define P_MII0_ERxD0   (P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(0))
+#define P_MII0_ERxD1   (P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(0))
+#define P_MII0_ERxD2   (P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(0))
+#define P_MII0_ERxD3   (P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(0))
+#define P_MII0_ERxDV   (P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(0))
+#define P_MII0_ERxCLK  (P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(0))
+#define P_MII0_ERxER   (P_DEFINED | P_IDENT(GPIO_PH14) | P_FUNCT(0))
+#define P_MII0_CRS     (P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(0))
+#define P_RMII0_REF_CLK        (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(1))
+#define P_RMII0_MDINT  (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(1))
+#define P_RMII0_CRS_DV (P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(1))
+
+#define PORT_PJ0       (GPIO_PH15 + 1)
+#define PORT_PJ1       (GPIO_PH15 + 2)
+#define PORT_PJ2       (GPIO_PH15 + 3)
+#define PORT_PJ3       (GPIO_PH15 + 4)
+#define PORT_PJ4       (GPIO_PH15 + 5)
+#define PORT_PJ5       (GPIO_PH15 + 6)
+#define PORT_PJ6       (GPIO_PH15 + 7)
+#define PORT_PJ7       (GPIO_PH15 + 8)
+#define PORT_PJ8       (GPIO_PH15 + 9)
+#define PORT_PJ9       (GPIO_PH15 + 10)
+#define PORT_PJ10      (GPIO_PH15 + 11)
+#define PORT_PJ11      (GPIO_PH15 + 12)
+
+#define P_MDC          (P_DEFINED | P_IDENT(PORT_PJ0) | P_FUNCT(0))
+#define P_MDIO         (P_DEFINED | P_IDENT(PORT_PJ1) | P_FUNCT(0))
+#define P_TWI0_SCL     (P_DEFINED | P_IDENT(PORT_PJ2) | P_FUNCT(0))
+#define P_TWI0_SDA     (P_DEFINED | P_IDENT(PORT_PJ3) | P_FUNCT(0))
+#define P_SPORT0_DRSEC (P_DEFINED | P_IDENT(PORT_PJ4) | P_FUNCT(0))
+#define P_SPORT0_DTSEC (P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(0))
+#define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(PORT_PJ6) | P_FUNCT(0))
+#define P_SPORT0_RFS   (P_DEFINED | P_IDENT(PORT_PJ7) | P_FUNCT(0))
+#define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(PORT_PJ8) | P_FUNCT(0))
+#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(PORT_PJ9) | P_FUNCT(0))
+#define P_SPORT0_TFS   (P_DEFINED | P_IDENT(PORT_PJ10) | P_FUNCT(0))
+#define P_SPORT0_DTPRI (P_DEFINED | P_IDENT(PORT_PJ11) | P_FUNCT(1))
+#define P_CAN0_RX      (P_DEFINED | P_IDENT(PORT_PJ4) | P_FUNCT(1))
+#define P_CAN0_TX      (P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(1))
+#define P_SPI0_SSEL3   (P_DEFINED | P_IDENT(PORT_PJ10) | P_FUNCT(1))
+#define P_SPI0_SSEL2   (P_DEFINED | P_IDENT(PORT_PJ11) | P_FUNCT(1))
+#define P_SPI0_SSEL7   (P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(2))
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/include/asm-blackfin/mach-bf548/anomaly.h b/include/asm-blackfin/mach-bf548/anomaly.h
new file mode 100644 (file)
index 0000000..aca1d4b
--- /dev/null
@@ -0,0 +1,74 @@
+
+/*
+ * File:         include/asm-blackfin/mach-bf548/anomaly.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * 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, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_ANOMALY_H_
+#define _MACH_ANOMALY_H_
+#define ANOMALY_05000074 /* A multi issue instruction with dsp32shiftimm in
+                           slot1 and store of a P register in slot 2 is not
+                           supported */
+#define ANOMALY_05000119 /* DMA_RUN bit is not valid after a Peripheral Receive
+                           Channel DMA stops */
+#define ANOMALY_05000122 /* Rx.H can not be used to access 16-bit System MMR
+                           registers. */
+#define ANOMALY_05000245 /* Spurious Hardware Error from an Access in the
+                           Shadow of a Conditional Branch */
+#define ANOMALY_05000255 /* Entering Hibernate Mode with RTC Seconds event
+                           interrupt not functional */
+#define ANOMALY_05000265 /* Sensitivity to noise with slow input edge rates on
+                           SPORT external receive and transmit clocks. */
+#define ANOMALY_05000272 /* Certain data cache write through modes fail for
+                           VDDint <=0.9V */
+#define ANOMALY_05000281 /* False Hardware Error Exception when ISR context is
+                           not restored */
+#define ANOMALY_05000310 /* False Hardware Errors Caused by Fetches at the
+                           Boundary of Reserved Memory */
+#define ANOMALY_05000312 /* Errors When SSYNC, CSYNC, or Loads to LT, LB and
+                           LC Registers Are Interrupted */
+#define ANOMALY_05000324 /* TWI Slave Boot Mode Is Not Functional */
+#define ANOMALY_05000325 /* External FIFO Boot Mode Is Not Functional */
+#define ANOMALY_05000327 /* Data Lost When Core and DMA Accesses Are Made to
+                           the USB FIFO Simultaneously */
+#define ANOMALY_05000328 /* Incorrect Access of OTP_STATUS During otp_write()
+                           function */
+#define ANOMALY_05000329 /* Synchronous Burst Flash Boot Mode Is Not Functional
+                           */
+#define ANOMALY_05000330 /* Host DMA Boot Mode Is Not Functional */
+#define ANOMALY_05000334 /* Inadequate Timing Margins on DDR DQS to DQ and DQM
+                           Skew */
+#define ANOMALY_05000335 /* Inadequate Rotary Debounce Logic Duration */
+#define ANOMALY_05000336 /* Phantom Interrupt Occurs After First Configuration
+                           of Host DMA Port */
+#define ANOMALY_05000337 /* Disallowed Configuration Prevents Subsequent
+                           Allowed Configuration on Host DMA Port */
+#define ANOMALY_05000338 /* Slave-Mode SPI0 MISO Failure With CPHA = 0 */
+
+#endif /* _MACH_ANOMALY_H_ */
diff --git a/include/asm-blackfin/mach-bf548/bf548.h b/include/asm-blackfin/mach-bf548/bf548.h
new file mode 100644 (file)
index 0000000..9498313
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/bf548.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  System MMR register and memory map for ADSP-BF548
+ *
+ * Modified:
+ *               Copyright 2004-2007 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
+ */
+
+#ifndef __MACH_BF548_H__
+#define __MACH_BF548_H__
+
+#define SUPPORTED_REVID 0
+
+#define OFFSET_(x) ((x) & 0x0000FFFF)
+
+/*some misc defines*/
+#define IMASK_IVG15            0x8000
+#define IMASK_IVG14            0x4000
+#define IMASK_IVG13            0x2000
+#define IMASK_IVG12            0x1000
+
+#define IMASK_IVG11            0x0800
+#define IMASK_IVG10            0x0400
+#define IMASK_IVG9             0x0200
+#define IMASK_IVG8             0x0100
+
+#define IMASK_IVG7             0x0080
+#define IMASK_IVGTMR   0x0040
+#define IMASK_IVGHW            0x0020
+
+/***************************/
+
+
+#define BLKFIN_DSUBBANKS       4
+#define BLKFIN_DWAYS           2
+#define BLKFIN_DLINES          64
+#define BLKFIN_ISUBBANKS       4
+#define BLKFIN_IWAYS           4
+#define BLKFIN_ILINES          32
+
+#define WAY0_L                 0x1
+#define WAY1_L                 0x2
+#define WAY01_L                        0x3
+#define WAY2_L                 0x4
+#define WAY02_L                        0x5
+#define        WAY12_L                 0x6
+#define        WAY012_L                0x7
+
+#define        WAY3_L                  0x8
+#define        WAY03_L                 0x9
+#define        WAY13_L                 0xA
+#define        WAY013_L                0xB
+
+#define        WAY32_L                 0xC
+#define        WAY320_L                0xD
+#define        WAY321_L                0xE
+#define        WAYALL_L                0xF
+
+#define DMC_ENABLE (2<<2)      /*yes, 2, not 1 */
+
+/********************************* EBIU Settings ************************************/
+#define AMBCTL0VAL     ((CONFIG_BANK_1 << 16) | CONFIG_BANK_0)
+#define AMBCTL1VAL     ((CONFIG_BANK_3 << 16) | CONFIG_BANK_2)
+
+#ifdef CONFIG_C_AMBEN_ALL
+#define V_AMBEN AMBEN_ALL
+#endif
+#ifdef CONFIG_C_AMBEN
+#define V_AMBEN 0x0
+#endif
+#ifdef CONFIG_C_AMBEN_B0
+#define V_AMBEN AMBEN_B0
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1
+#define V_AMBEN AMBEN_B0_B1
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1_B2
+#define V_AMBEN AMBEN_B0_B1_B2
+#endif
+#ifdef CONFIG_C_AMCKEN
+#define V_AMCKEN AMCKEN
+#else
+#define V_AMCKEN 0x0
+#endif
+
+#define AMGCTLVAL      (V_AMBEN | V_AMCKEN)
+
+#define MAX_VC 650000000
+#define MIN_VC 50000000
+
+/********************************PLL Settings **************************************/
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
+#if (CONFIG_VCO_MULT < 0)
+#error "VCO Multiplier is less than 0. Please select a different value"
+#endif
+
+#if (CONFIG_VCO_MULT == 0)
+#error "VCO Multiplier should be greater than 0. Please select a different value"
+#endif
+
+#if (CONFIG_VCO_MULT > 64)
+#error "VCO Multiplier is more than 64. Please select a different value"
+#endif
+
+#ifndef CONFIG_CLKIN_HALF
+#define CONFIG_VCO_HZ  (CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)
+#else
+#define CONFIG_VCO_HZ  ((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)/2)
+#endif
+
+#ifndef CONFIG_PLL_BYPASS
+#define CONFIG_CCLK_HZ (CONFIG_VCO_HZ/CONFIG_CCLK_DIV)
+#define CONFIG_SCLK_HZ (CONFIG_VCO_HZ/CONFIG_SCLK_DIV)
+#else
+#define CONFIG_CCLK_HZ CONFIG_CLKIN_HZ
+#define CONFIG_SCLK_HZ CONFIG_CLKIN_HZ
+#endif
+
+#if (CONFIG_SCLK_DIV < 1)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_SCLK_DIV > 15)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_CCLK_DIV != 1)
+#if (CONFIG_CCLK_DIV != 2)
+#if (CONFIG_CCLK_DIV != 4)
+#if (CONFIG_CCLK_DIV != 8)
+#error "CCLK DIV can be 1,2,4 or 8 only. Please select a proper value"
+#endif
+#endif
+#endif
+#endif
+
+#if (CONFIG_VCO_HZ > MAX_VC)
+#error "VCO selected is more than maximum value. Please change the VCO multipler"
+#endif
+
+#if (CONFIG_SCLK_HZ > 133000000)
+#error "Sclk value selected is more than maximum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ < 27000000)
+#error "Sclk value selected is less than minimum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ >= CONFIG_CCLK_HZ)
+#if (CONFIG_SCLK_HZ != CONFIG_CLKIN_HZ)
+#if (CONFIG_CCLK_HZ != CONFIG_CLKIN_HZ)
+#error "Please select sclk less than cclk"
+#endif
+#endif
+#endif
+
+#if (CONFIG_CCLK_DIV == 1)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV1
+#endif
+#if (CONFIG_CCLK_DIV == 2)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV2
+#endif
+#if (CONFIG_CCLK_DIV == 4)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV4
+#endif
+#if (CONFIG_CCLK_DIV == 8)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV8
+#endif
+#ifndef CONFIG_CCLK_ACT_DIV
+#define CONFIG_CCLK_ACT_DIV   CONFIG_CCLK_DIV_not_defined_properly
+#endif
+
+#endif /* CONFIG_BFIN_KERNEL_CLOCK */
+
+#ifdef CONFIG_BF542
+#define CPU "BF542"
+#define CPUID 0x027c8000
+#endif
+#ifdef CONFIG_BF544
+#define CPU "BF544"
+#define CPUID 0x027c8000
+#endif
+#ifdef CONFIG_BF548
+#define CPU "BF548"
+#define CPUID 0x027c6000
+#endif
+#ifdef CONFIG_BF549
+#define CPU "BF549"
+#endif
+#ifndef CPU
+#define        CPU "UNKNOWN"
+#define CPUID 0x0
+#endif
+
+#if (CONFIG_MEM_SIZE % 4)
+#error "SDRAM mem size must be multible of 4MB"
+#endif
+
+#define SDRAM_IGENERIC    (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO)
+#define SDRAM_IKERNEL     (SDRAM_IGENERIC | CPLB_LOCK)
+#define L1_IMEMORY        (               CPLB_USER_RD | CPLB_VALID | CPLB_LOCK)
+#define SDRAM_INON_CHBL   (               CPLB_USER_RD | CPLB_VALID)
+
+/*Use the menuconfig cache policy here - CONFIG_BLKFIN_WT/CONFIG_BLKFIN_WB*/
+
+#define ANOMALY_05000158_WORKAROUND            0x200
+#ifdef CONFIG_BLKFIN_WB                /*Write Back Policy */
+#define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_DIRTY \
+                       | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND)
+#else                          /*Write Through */
+#define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW \
+                       | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#endif
+
+
+#define L1_DMEMORY       (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY )
+#define SDRAM_DNON_CHBL  (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#define SDRAM_EBIU       (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#define SDRAM_OOPS      (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY )
+
+#define SIZE_1K 0x00000400     /* 1K */
+#define SIZE_4K 0x00001000     /* 4K */
+#define SIZE_1M 0x00100000     /* 1M */
+#define SIZE_4M 0x00400000     /* 4M */
+
+#define MAX_CPLBS (16 * 2)
+
+/*
+* Number of required data CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 16 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Data Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+* 1 for ASYNC Memory
+*/
+
+
+#define MAX_SWITCH_D_CPLBS (((CONFIG_MEM_SIZE / 4) + 16 + 1 + 1 + 1) * 2)
+
+/*
+* Number of required instruction CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 12 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Instruction Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+*/
+
+#define MAX_SWITCH_I_CPLBS (((CONFIG_MEM_SIZE / 4) + 12 + 1 + 1) * 2)
+
+#endif /* __MACH_BF48_H__  */
diff --git a/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
new file mode 100644 (file)
index 0000000..2f4afc9
--- /dev/null
@@ -0,0 +1,193 @@
+#include <linux/serial.h>
+#include <asm/dma.h>
+
+#define NR_PORTS               4
+
+#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
+#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
+#define OFFSET_GCTL             0x08   /* Global Control Register              */
+#define OFFSET_LCR              0x0C   /* Line Control Register                */
+#define OFFSET_MCR              0x10   /* Modem Control Register               */
+#define OFFSET_LSR              0x14   /* Line Status Register                 */
+#define OFFSET_MSR              0x18   /* Modem Status Register                */
+#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
+#define OFFSET_IER_SET          0x20   /* Set Interrupt Enable Register        */
+#define OFFSET_IER_CLEAR        0x24   /* Clear Interrupt Enable Register      */
+#define OFFSET_THR              0x28   /* Transmit Holding register            */
+#define OFFSET_RBR              0x2C   /* Receive Buffer register              */
+
+#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
+#define UART_GET_DLL(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLL))
+#define UART_GET_DLH(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLH))
+#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER_SET))
+#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
+#define UART_GET_LSR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LSR))
+#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
+
+#define UART_PUT_CHAR(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_THR),v)
+#define UART_PUT_DLL(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLL),v)
+#define UART_SET_IER(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_IER_SET),v)
+#define UART_CLEAR_IER(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_IER_CLEAR),v)
+#define UART_PUT_DLH(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
+#define UART_PUT_LSR(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_LSR),v)
+#define UART_PUT_LCR(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
+#define UART_PUT_GCTL(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
+
+#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
+# define CONFIG_SERIAL_BFIN_CTSRTS
+
+# ifndef CONFIG_UART0_CTS_PIN
+#  define CONFIG_UART0_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART0_RTS_PIN
+#  define CONFIG_UART0_RTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_CTS_PIN
+#  define CONFIG_UART1_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_RTS_PIN
+#  define CONFIG_UART1_RTS_PIN -1
+# endif
+#endif
+/*
+ * The pin configuration is different from schematic
+ */
+struct bfin_serial_port {
+        struct uart_port        port;
+        unsigned int            old_status;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       int                     tx_done;
+       int                     tx_count;
+       struct circ_buf         rx_dma_buf;
+       struct timer_list       rx_dma_timer;
+       int                     rx_dma_nrows;
+       unsigned int            tx_dma_channel;
+       unsigned int            rx_dma_channel;
+       struct work_struct      tx_dma_workqueue;
+#else
+       struct work_struct      cts_workqueue;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       int             cts_pin;
+       int             rts_pin;
+#endif
+};
+
+struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_res {
+       unsigned long   uart_base_addr;
+       int             uart_irq;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       unsigned int    uart_tx_dma_channel;
+       unsigned int    uart_rx_dma_channel;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       int     uart_cts_pin;
+       int     uart_rts_pin;
+#endif
+};
+
+struct bfin_serial_res bfin_serial_resource[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+       {
+       0xFFC00400,
+       IRQ_UART0_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       CH_UART0_TX,
+       CH_UART0_RX,
+#endif
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+       CONFIG_UART0_CTS_PIN,
+       CONFIG_UART0_RTS_PIN,
+#endif
+       },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+       {
+       0xFFC02000,
+       IRQ_UART1_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       CH_UART1_TX,
+       CH_UART1_RX,
+#endif
+       },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART2
+       {
+       0xFFC02100,
+       IRQ_UART2_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       CH_UART2_TX,
+       CH_UART2_RX,
+#endif
+#ifdef CONFIG_BFIN_UART2_CTSRTS
+       CONFIG_UART2_CTS_PIN,
+       CONFIG_UART2_RTS_PIN,
+#endif
+       },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART3
+       {
+       0xFFC03100,
+       IRQ_UART3_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       CH_UART3_TX,
+       CH_UART3_RX,
+#endif
+       },
+#endif
+};
+
+int nr_ports = ARRAY_SIZE(bfin_serial_resource);
+
+static void bfin_serial_hw_init(struct bfin_serial_port *uart)
+{
+#ifdef CONFIG_SERIAL_BFIN_UART0
+       /* Enable UART0 RX and TX on pin 7 & 8 of PORT E */
+       bfin_write_PORTE_FER(0x180 | bfin_read_PORTE_FER());
+       bfin_write_PORTE_MUX(0x3C000 | bfin_read_PORTE_MUX());
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART1
+       /* Enable UART1 RX and TX on pin 0 & 1 of PORT H */
+       bfin_write_PORTH_FER(0x3 | bfin_read_PORTH_FER());
+       bfin_write_PORTH_MUX(~0xF & bfin_read_PORTH_MUX());
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+       /* Enable UART1 RTS and CTS on pin 9 & 10 of PORT E */
+       bfin_write_PORTE_FER(0x600 | bfin_read_PORTE_FER());
+       bfin_write_PORTE_MUX(~0x3C0000 & bfin_read_PORTE_MUX());
+#endif
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART2
+       /* Enable UART2 RX and TX on pin 4 & 5 of PORT B */
+       bfin_write_PORTB_FER(0x30 | bfin_read_PORTB_FER());
+       bfin_write_PORTB_MUX(~0xF00 & bfin_read_PORTB_MUX());
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART3
+       /* Enable UART3 RX and TX on pin 6 & 7 of PORT B */
+       bfin_write_PORTB_FER(0xC0 | bfin_read_PORTB_FER());
+       bfin_write_PORTB_MUX(~0xF000 | bfin_read_PORTB_MUX());
+#ifdef CONFIG_BFIN_UART3_CTSRTS
+       /* Enable UART3 RTS and CTS on pin 2 & 3 of PORT B */
+       bfin_write_PORTB_FER(0xC | bfin_read_PORTB_FER());
+       bfin_write_PORTB_MUX(~0xF0 | bfin_read_PORTB_MUX());
+#endif
+#endif
+       SSYNC();
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       if (uart->cts_pin >= 0) {
+               gpio_request(uart->cts_pin, NULL);
+               gpio_direction_input(uart->cts_pin);
+       }
+
+       if (uart->rts_pin >= 0) {
+               gpio_request(uart->rts_pin, NULL);
+               gpio_direction_output(uart->rts_pin);
+       }
+#endif
+}
diff --git a/include/asm-blackfin/mach-bf548/blackfin.h b/include/asm-blackfin/mach-bf548/blackfin.h
new file mode 100644 (file)
index 0000000..791218f
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/blackfin.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * 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, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_BLACKFIN_H_
+#define _MACH_BLACKFIN_H_
+
+#define BF548_FAMILY
+
+#include "bf548.h"
+#include "mem_map.h"
+#include "anomaly.h"
+
+#ifdef CONFIG_BF542
+#include "defBF542.h"
+#endif
+
+#ifdef CONFIG_BF544
+#include "defBF544.h"
+#endif
+
+#ifdef CONFIG_BF548
+#include "defBF548.h"
+#endif
+
+#ifdef CONFIG_BF549
+#include "defBF549.h"
+#endif
+
+#if !(defined(__ASSEMBLY__) || defined(ASSEMBLY))
+#ifdef CONFIG_BF542
+#include "cdefBF542.h"
+#endif
+
+#ifdef CONFIG_BF544
+#include "cdefBF544.h"
+#endif
+#ifdef CONFIG_BF548
+#include "cdefBF548.h"
+#endif
+#ifdef CONFIG_BF549
+#include "cdefBF549.h"
+#endif
+
+/* UART 1*/
+#define bfin_read_UART_THR()           bfin_read_UART1_THR()
+#define bfin_write_UART_THR(val)       bfin_write_UART1_THR(val)
+#define bfin_read_UART_RBR()           bfin_read_UART1_RBR()
+#define bfin_write_UART_RBR(val)       bfin_write_UART1_RBR(val)
+#define bfin_read_UART_DLL()           bfin_read_UART1_DLL()
+#define bfin_write_UART_DLL(val)       bfin_write_UART1_DLL(val)
+#define bfin_read_UART_IER()           bfin_read_UART1_IER()
+#define bfin_write_UART_IER(val)       bfin_write_UART1_IER(val)
+#define bfin_read_UART_DLH()           bfin_read_UART1_DLH()
+#define bfin_write_UART_DLH(val)       bfin_write_UART1_DLH(val)
+#define bfin_read_UART_IIR()           bfin_read_UART1_IIR()
+#define bfin_write_UART_IIR(val)       bfin_write_UART1_IIR(val)
+#define bfin_read_UART_LCR()           bfin_read_UART1_LCR()
+#define bfin_write_UART_LCR(val)       bfin_write_UART1_LCR(val)
+#define bfin_read_UART_MCR()           bfin_read_UART1_MCR()
+#define bfin_write_UART_MCR(val)       bfin_write_UART1_MCR(val)
+#define bfin_read_UART_LSR()           bfin_read_UART1_LSR()
+#define bfin_write_UART_LSR(val)       bfin_write_UART1_LSR(val)
+#define bfin_read_UART_SCR()           bfin_read_UART1_SCR()
+#define bfin_write_UART_SCR(val)       bfin_write_UART1_SCR(val)
+#define bfin_read_UART_GCTL()          bfin_read_UART1_GCTL()
+#define bfin_write_UART_GCTL(val)      bfin_write_UART1_GCTL(val)
+
+#endif
+
+/* MAP used DEFINES from BF533 to BF54x - so we don't need to change 
+ * them in the driver, kernel, etc. */
+
+/* UART_IIR Register */
+#define STATUS(x)      ((x << 1) & 0x06)
+#define STATUS_P1      0x02
+#define STATUS_P0      0x01
+
+/* UART 0*/
+
+/* DMA Channnel */
+#define bfin_read_CH_UART_RX()         bfin_read_CH_UART1_RX()
+#define bfin_write_CH_UART_RX(val)     bfin_write_CH_UART1_RX(val)
+#define bfin_read_CH_UART_TX()         bfin_read_CH_UART1_TX()
+#define bfin_write_CH_UART_TX(val)     bfin_write_CH_UART1_TX(val)
+#define CH_UART_RX                     CH_UART1_RX
+#define CH_UART_TX                     CH_UART1_TX
+
+/* System Interrupt Controller */
+#define bfin_read_IRQ_UART_RX()                bfin_read_IRQ_UART1_RX()
+#define bfin_write_IRQ_UART_RX(val)    bfin_write_IRQ_UART1_RX(val)
+#define bfin_read_IRQ_UART_TX()                bfin_read_IRQ_UART1_TX()
+#define bfin_write_IRQ_UART_TX(val)    bfin_write_IRQ_UART1_TX(val)
+#define bfin_read_IRQ_UART_ERROR()     bfin_read_IRQ_UART1_ERROR()
+#define bfin_write_IRQ_UART_ERROR(val) bfin_write_IRQ_UART1_ERROR(val)
+#define IRQ_UART_RX                    IRQ_UART1_RX
+#define        IRQ_UART_TX                     IRQ_UART1_TX
+#define        IRQ_UART_ERROR                  IRQ_UART1_ERROR
+
+/* MMR Registers*/
+#define bfin_read_UART_THR()           bfin_read_UART1_THR()
+#define bfin_write_UART_THR(val)       bfin_write_UART1_THR(val)
+#define bfin_read_UART_RBR()           bfin_read_UART1_RBR()
+#define bfin_write_UART_RBR(val)       bfin_write_UART1_RBR(val)
+#define bfin_read_UART_DLL()           bfin_read_UART1_DLL()
+#define bfin_write_UART_DLL(val)       bfin_write_UART1_DLL(val)
+#define bfin_read_UART_IER()           bfin_read_UART1_IER()
+#define bfin_write_UART_IER(val)       bfin_write_UART1_IER(val)
+#define bfin_read_UART_DLH()           bfin_read_UART1_DLH()
+#define bfin_write_UART_DLH(val)       bfin_write_UART1_DLH(val)
+#define bfin_read_UART_IIR()           bfin_read_UART1_IIR()
+#define bfin_write_UART_IIR(val)       bfin_write_UART1_IIR(val)
+#define bfin_read_UART_LCR()           bfin_read_UART1_LCR()
+#define bfin_write_UART_LCR(val)       bfin_write_UART1_LCR(val)
+#define bfin_read_UART_MCR()           bfin_read_UART1_MCR()
+#define bfin_write_UART_MCR(val)       bfin_write_UART1_MCR(val)
+#define bfin_read_UART_LSR()           bfin_read_UART1_LSR()
+#define bfin_write_UART_LSR(val)       bfin_write_UART1_LSR(val)
+#define bfin_read_UART_SCR()           bfin_read_UART1_SCR()
+#define bfin_write_UART_SCR(val)       bfin_write_UART1_SCR(val)
+#define bfin_read_UART_GCTL()          bfin_read_UART1_GCTL()
+#define bfin_write_UART_GCTL(val)      bfin_write_UART1_GCTL(val)
+#define UART_THR                       UART1_THR
+#define UART_RBR                       UART1_RBR
+#define UART_DLL                       UART1_DLL
+#define UART_IER                       UART1_IER
+#define UART_DLH                       UART1_DLH
+#define UART_IIR                       UART1_IIR
+#define UART_LCR                       UART1_LCR
+#define UART_MCR                       UART1_MCR
+#define UART_LSR                       UART1_LSR
+#define UART_SCR                       UART1_SCR
+#define UART_GCTL                      UART1_GCTL
+
+/* PLL_DIV Masks */
+#define CCLK_DIV1 CSEL_DIV1    /* CCLK = VCO / 1 */
+#define CCLK_DIV2 CSEL_DIV2    /* CCLK = VCO / 2 */
+#define CCLK_DIV4 CSEL_DIV4    /* CCLK = VCO / 4 */
+#define CCLK_DIV8 CSEL_DIV8    /* CCLK = VCO / 8 */
+
+#endif
index 6bbcefeb3627c161e0a156bb467b2cda87109b6a..98d35a9291165d61cacc8167ac24b48d5724be1b 100644 (file)
@@ -31,7 +31,8 @@
 #ifndef _CDEF_BF54X_H
 #define _CDEF_BF54X_H
 
-#include <defBF54x_base.h>
+#include "defBF54x_base.h"
+#include <asm/system.h>
 
 /* ************************************************************** */
 /* SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF54x    */
 #define bfin_read_PLL_DIV()            bfin_read16(PLL_DIV)
 #define bfin_write_PLL_DIV(val)                bfin_write16(PLL_DIV, val)
 #define bfin_read_VR_CTL()             bfin_read16(VR_CTL)
-#define bfin_write_VR_CTL(val)         bfin_write16(VR_CTL, val)
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1, iwr2;
+
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       iwr2 = bfin_read32(SIC_IWR2);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+       bfin_write32(SIC_IWR2, 0);
+
+       bfin_write16(VR_CTL, val);
+       __builtin_bfin_ssync();
+
+       local_irq_save(flags);
+       asm("IDLE;");
+       local_irq_restore(flags);
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       bfin_write32(SIC_IWR2, iwr2);
+}
 #define bfin_read_PLL_STAT()           bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)       bfin_write16(PLL_STAT, val)
 #define bfin_read_PLL_LOCKCNT()                bfin_read16(PLL_LOCKCNT)
 #define bfin_write_SIC_IMASK1(val)     bfin_write32(SIC_IMASK1, val)
 #define bfin_read_SIC_IMASK2()         bfin_read32(SIC_IMASK2)
 #define bfin_write_SIC_IMASK2(val)     bfin_write32(SIC_IMASK2, val)
+#define bfin_read_SIC_IMASK(x)         bfin_read32(SIC_IMASK0 + (x << 2))
+#define bfin_write_SIC_IMASK(x, val)   bfin_write32((SIC_IMASK0 + (x << 2)), val)
+
 #define bfin_read_SIC_ISR0()           bfin_read32(SIC_ISR0)
 #define bfin_write_SIC_ISR0(val)       bfin_write32(SIC_ISR0, val)
 #define bfin_read_SIC_ISR1()           bfin_read32(SIC_ISR1)
 #define bfin_write_SIC_ISR1(val)       bfin_write32(SIC_ISR1, val)
 #define bfin_read_SIC_ISR2()           bfin_read32(SIC_ISR2)
 #define bfin_write_SIC_ISR2(val)       bfin_write32(SIC_ISR2, val)
+#define bfin_read_SIC_ISR(x)           bfin_read32(SIC_ISR0 + (x << 2))
+#define bfin_write_SIC_ISR(x, val)     bfin_write32((SIC_ISR0 + (x << 2)), val)
+
 #define bfin_read_SIC_IWR0()           bfin_read32(SIC_IWR0)
 #define bfin_write_SIC_IWR0(val)       bfin_write32(SIC_IWR0, val)
 #define bfin_read_SIC_IWR1()           bfin_read32(SIC_IWR1)
 #define bfin_read_MDMA_D0_NEXT_DESC_PTR()      bfin_read32(MDMA_D0_NEXT_DESC_PTR)
 #define bfin_write_MDMA_D0_NEXT_DESC_PTR(val)  bfin_write32(MDMA_D0_NEXT_DESC_PTR)
 #define bfin_read_MDMA_D0_START_ADDR()                 bfin_read32(MDMA_D0_START_ADDR)
-#define bfin_write_MDMA_D0_START_ADDR(val)     bfin_write32(MDMA_D0_START_ADDR)
+#define bfin_write_MDMA_D0_START_ADDR(val)     bfin_write32(MDMA_D0_START_ADDR, val)
 #define bfin_read_MDMA_D0_CONFIG()             bfin_read16(MDMA_D0_CONFIG)
 #define bfin_write_MDMA_D0_CONFIG(val)         bfin_write16(MDMA_D0_CONFIG, val)
 #define bfin_read_MDMA_D0_X_COUNT()            bfin_read16(MDMA_D0_X_COUNT)
 #define bfin_write_MDMA_D0_X_COUNT(val)                bfin_write16(MDMA_D0_X_COUNT, val)
 #define bfin_read_MDMA_D0_X_MODIFY()           bfin_read16(MDMA_D0_X_MODIFY)
-#define bfin_write_MDMA_D0_X_MODIFY(val)       bfin_write16(MDMA_D0_X_MODIFY)
+#define bfin_write_MDMA_D0_X_MODIFY(val)       bfin_write16(MDMA_D0_X_MODIFY, val)
 #define bfin_read_MDMA_D0_Y_COUNT()            bfin_read16(MDMA_D0_Y_COUNT)
 #define bfin_write_MDMA_D0_Y_COUNT(val)                bfin_write16(MDMA_D0_Y_COUNT, val)
 #define bfin_read_MDMA_D0_Y_MODIFY()           bfin_read16(MDMA_D0_Y_MODIFY)
-#define bfin_write_MDMA_D0_Y_MODIFY(val)       bfin_write16(MDMA_D0_Y_MODIFY)
+#define bfin_write_MDMA_D0_Y_MODIFY(val)       bfin_write16(MDMA_D0_Y_MODIFY, val)
 #define bfin_read_MDMA_D0_CURR_DESC_PTR()      bfin_read32(MDMA_D0_CURR_DESC_PTR)
-#define bfin_write_MDMA_D0_CURR_DESC_PTR(val)  bfin_write32(MDMA_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA_D0_CURR_DESC_PTR(val)  bfin_write32(MDMA_D0_CURR_DESC_PTR, val)
 #define bfin_read_MDMA_D0_CURR_ADDR()          bfin_read32(MDMA_D0_CURR_ADDR)
-#define bfin_write_MDMA_D0_CURR_ADDR(val)      bfin_write32(MDMA_D0_CURR_ADDR)
+#define bfin_write_MDMA_D0_CURR_ADDR(val)      bfin_write32(MDMA_D0_CURR_ADDR, val)
 #define bfin_read_MDMA_D0_IRQ_STATUS()         bfin_read16(MDMA_D0_IRQ_STATUS)
 #define bfin_write_MDMA_D0_IRQ_STATUS(val)     bfin_write16(MDMA_D0_IRQ_STATUS, val)
 #define bfin_read_MDMA_D0_PERIPHERAL_MAP()     bfin_read16(MDMA_D0_PERIPHERAL_MAP)
 #define bfin_read_MDMA_D0_CURR_Y_COUNT()       bfin_read16(MDMA_D0_CURR_Y_COUNT)
 #define bfin_write_MDMA_D0_CURR_Y_COUNT(val)   bfin_write16(MDMA_D0_CURR_Y_COUNT, val)
 #define bfin_read_MDMA_S0_NEXT_DESC_PTR()      bfin_read32(MDMA_S0_NEXT_DESC_PTR)
-#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val)  bfin_write32(MDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val)  bfin_write32(MDMA_S0_NEXT_DESC_PTR, val)
 #define bfin_read_MDMA_S0_START_ADDR()                 bfin_read32(MDMA_S0_START_ADDR)
-#define bfin_write_MDMA_S0_START_ADDR(val)     bfin_write32(MDMA_S0_START_ADDR)
+#define bfin_write_MDMA_S0_START_ADDR(val)     bfin_write32(MDMA_S0_START_ADDR, val)
 #define bfin_read_MDMA_S0_CONFIG()             bfin_read16(MDMA_S0_CONFIG)
 #define bfin_write_MDMA_S0_CONFIG(val)         bfin_write16(MDMA_S0_CONFIG, val)
 #define bfin_read_MDMA_S0_X_COUNT()            bfin_read16(MDMA_S0_X_COUNT)
 #define bfin_write_MDMA_S0_X_COUNT(val)                bfin_write16(MDMA_S0_X_COUNT, val)
 #define bfin_read_MDMA_S0_X_MODIFY()           bfin_read16(MDMA_S0_X_MODIFY)
-#define bfin_write_MDMA_S0_X_MODIFY(val)       bfin_write16(MDMA_S0_X_MODIFY)
+#define bfin_write_MDMA_S0_X_MODIFY(val)       bfin_write16(MDMA_S0_X_MODIFY, val)
 #define bfin_read_MDMA_S0_Y_COUNT()            bfin_read16(MDMA_S0_Y_COUNT)
 #define bfin_write_MDMA_S0_Y_COUNT(val)                bfin_write16(MDMA_S0_Y_COUNT, val)
 #define bfin_read_MDMA_S0_Y_MODIFY()           bfin_read16(MDMA_S0_Y_MODIFY)
-#define bfin_write_MDMA_S0_Y_MODIFY(val)       bfin_write16(MDMA_S0_Y_MODIFY)
+#define bfin_write_MDMA_S0_Y_MODIFY(val)       bfin_write16(MDMA_S0_Y_MODIFY, val)
 #define bfin_read_MDMA_S0_CURR_DESC_PTR()      bfin_read32(MDMA_S0_CURR_DESC_PTR)
-#define bfin_write_MDMA_S0_CURR_DESC_PTR(val)  bfin_write32(MDMA_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA_S0_CURR_DESC_PTR(val)  bfin_write32(MDMA_S0_CURR_DESC_PTR, val)
 #define bfin_read_MDMA_S0_CURR_ADDR()          bfin_read32(MDMA_S0_CURR_ADDR)
-#define bfin_write_MDMA_S0_CURR_ADDR(val)      bfin_write32(MDMA_S0_CURR_ADDR)
+#define bfin_write_MDMA_S0_CURR_ADDR(val)      bfin_write32(MDMA_S0_CURR_ADDR, val)
 #define bfin_read_MDMA_S0_IRQ_STATUS()         bfin_read16(MDMA_S0_IRQ_STATUS)
 #define bfin_write_MDMA_S0_IRQ_STATUS(val)     bfin_write16(MDMA_S0_IRQ_STATUS, val)
 #define bfin_read_MDMA_S0_PERIPHERAL_MAP()     bfin_read16(MDMA_S0_PERIPHERAL_MAP)
 /* MDMA Stream 1 Registers */
 
 #define bfin_read_MDMA_D1_NEXT_DESC_PTR()      bfin_read32(MDMA_D1_NEXT_DESC_PTR)
-#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val)  bfin_write32(MDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val)  bfin_write32(MDMA_D1_NEXT_DESC_PTR, val)
 #define bfin_read_MDMA_D1_START_ADDR()                 bfin_read32(MDMA_D1_START_ADDR)
-#define bfin_write_MDMA_D1_START_ADDR(val)     bfin_write32(MDMA_D1_START_ADDR)
+#define bfin_write_MDMA_D1_START_ADDR(val)     bfin_write32(MDMA_D1_START_ADDR, val)
 #define bfin_read_MDMA_D1_CONFIG()             bfin_read16(MDMA_D1_CONFIG)
 #define bfin_write_MDMA_D1_CONFIG(val)         bfin_write16(MDMA_D1_CONFIG, val)
 #define bfin_read_MDMA_D1_X_COUNT()            bfin_read16(MDMA_D1_X_COUNT)
 #define bfin_read_MDMA_D1_Y_MODIFY()           bfin_read16(MDMA_D1_Y_MODIFY)
 #define bfin_write_MDMA_D1_Y_MODIFY(val)       bfin_write16(MDMA_D1_Y_MODIFY)
 #define bfin_read_MDMA_D1_CURR_DESC_PTR()      bfin_read32(MDMA_D1_CURR_DESC_PTR)
-#define bfin_write_MDMA_D1_CURR_DESC_PTR(val)  bfin_write32(MDMA_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA_D1_CURR_DESC_PTR(val)  bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
 #define bfin_read_MDMA_D1_CURR_ADDR()          bfin_read32(MDMA_D1_CURR_ADDR)
-#define bfin_write_MDMA_D1_CURR_ADDR(val)      bfin_write32(MDMA_D1_CURR_ADDR)
+#define bfin_write_MDMA_D1_CURR_ADDR(val)      bfin_write32(MDMA_D1_CURR_ADDR, val)
 #define bfin_read_MDMA_D1_IRQ_STATUS()         bfin_read16(MDMA_D1_IRQ_STATUS)
 #define bfin_write_MDMA_D1_IRQ_STATUS(val)     bfin_write16(MDMA_D1_IRQ_STATUS, val)
 #define bfin_read_MDMA_D1_PERIPHERAL_MAP()     bfin_read16(MDMA_D1_PERIPHERAL_MAP)
 #define bfin_read_MDMA_D1_CURR_Y_COUNT()       bfin_read16(MDMA_D1_CURR_Y_COUNT)
 #define bfin_write_MDMA_D1_CURR_Y_COUNT(val)   bfin_write16(MDMA_D1_CURR_Y_COUNT, val)
 #define bfin_read_MDMA_S1_NEXT_DESC_PTR()      bfin_read32(MDMA_S1_NEXT_DESC_PTR)
-#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val)  bfin_write32(MDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val)  bfin_write32(MDMA_S1_NEXT_DESC_PTR, val)
 #define bfin_read_MDMA_S1_START_ADDR()                 bfin_read32(MDMA_S1_START_ADDR)
-#define bfin_write_MDMA_S1_START_ADDR(val)     bfin_write32(MDMA_S1_START_ADDR)
+#define bfin_write_MDMA_S1_START_ADDR(val)     bfin_write32(MDMA_S1_START_ADDR, val)
 #define bfin_read_MDMA_S1_CONFIG()             bfin_read16(MDMA_S1_CONFIG)
 #define bfin_write_MDMA_S1_CONFIG(val)         bfin_write16(MDMA_S1_CONFIG, val)
 #define bfin_read_MDMA_S1_X_COUNT()            bfin_read16(MDMA_S1_X_COUNT)
 #define bfin_read_MDMA_S1_Y_MODIFY()           bfin_read16(MDMA_S1_Y_MODIFY)
 #define bfin_write_MDMA_S1_Y_MODIFY(val)       bfin_write16(MDMA_S1_Y_MODIFY)
 #define bfin_read_MDMA_S1_CURR_DESC_PTR()      bfin_read32(MDMA_S1_CURR_DESC_PTR)
-#define bfin_write_MDMA_S1_CURR_DESC_PTR(val)  bfin_write32(MDMA_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA_S1_CURR_DESC_PTR(val)  bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
 #define bfin_read_MDMA_S1_CURR_ADDR()          bfin_read32(MDMA_S1_CURR_ADDR)
-#define bfin_write_MDMA_S1_CURR_ADDR(val)      bfin_write32(MDMA_S1_CURR_ADDR)
+#define bfin_write_MDMA_S1_CURR_ADDR(val)      bfin_write32(MDMA_S1_CURR_ADDR, val)
 #define bfin_read_MDMA_S1_IRQ_STATUS()         bfin_read16(MDMA_S1_IRQ_STATUS)
 #define bfin_write_MDMA_S1_IRQ_STATUS(val)     bfin_write16(MDMA_S1_IRQ_STATUS, val)
 #define bfin_read_MDMA_S1_PERIPHERAL_MAP()     bfin_read16(MDMA_S1_PERIPHERAL_MAP)
index ac968fca5cc549bbb0e19555d6f9c4eb0961deb1..32d07130200c980587a0ef8d840b026f375b6fbd 100644 (file)
 /* Bit masks for KPAD_CTL */
 
 #define                   KPAD_EN  0x1        /* Keypad Enable */
-#define                  nKPAD_EN  0x0       
 #define              KPAD_IRQMODE  0x6        /* Key Press Interrupt Enable */
 #define                KPAD_ROWEN  0x1c00     /* Row Enable Width */
 #define                KPAD_COLEN  0xe000     /* Column Enable Width */
 /* Bit masks for KPAD_STAT */
 
 #define                  KPAD_IRQ  0x1        /* Keypad Interrupt Status */
-#define                 nKPAD_IRQ  0x0       
 #define              KPAD_MROWCOL  0x6        /* Multiple Row/Column Keypress Status */
 #define              KPAD_PRESSED  0x8        /* Key press current status */
-#define             nKPAD_PRESSED  0x0       
 
 /* Bit masks for KPAD_SOFTEVAL */
 
 #define           KPAD_SOFTEVAL_E  0x2        /* Software Programmable Force Evaluate */
-#define          nKPAD_SOFTEVAL_E  0x0       
 
 /* Bit masks for SDH_COMMAND */
 
 #define                   CMD_IDX  0x3f       /* Command Index */
 #define                   CMD_RSP  0x40       /* Response */
-#define                  nCMD_RSP  0x0       
 #define                 CMD_L_RSP  0x80       /* Long Response */
-#define                nCMD_L_RSP  0x0       
 #define                 CMD_INT_E  0x100      /* Command Interrupt */
-#define                nCMD_INT_E  0x0       
 #define                CMD_PEND_E  0x200      /* Command Pending */
-#define               nCMD_PEND_E  0x0       
 #define                     CMD_E  0x400      /* Command Enable */
-#define                    nCMD_E  0x0       
 
 /* Bit masks for SDH_PWR_CTL */
 
 #define                       TBD  0x3c       /* TBD */
 #endif
 #define                 SD_CMD_OD  0x40       /* Open Drain Output */
-#define                nSD_CMD_OD  0x0       
 #define                   ROD_CTL  0x80       /* Rod Control */
-#define                  nROD_CTL  0x0       
 
 /* Bit masks for SDH_CLK_CTL */
 
 #define                    CLKDIV  0xff       /* MC_CLK Divisor */
 #define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
-#define                    nCLK_E  0x0       
 #define                  PWR_SV_E  0x200      /* Power Save Enable */
-#define                 nPWR_SV_E  0x0       
 #define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
-#define            nCLKDIV_BYPASS  0x0       
 #define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
-#define                 nWIDE_BUS  0x0       
 
 /* Bit masks for SDH_RESP_CMD */
 
 /* Bit masks for SDH_DATA_CTL */
 
 #define                     DTX_E  0x1        /* Data Transfer Enable */
-#define                    nDTX_E  0x0       
 #define                   DTX_DIR  0x2        /* Data Transfer Direction */
-#define                  nDTX_DIR  0x0       
 #define                  DTX_MODE  0x4        /* Data Transfer Mode */
-#define                 nDTX_MODE  0x0       
 #define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
-#define                nDTX_DMA_E  0x0       
 #define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
 
 /* Bit masks for SDH_STATUS */
 
 #define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
-#define             nCMD_CRC_FAIL  0x0       
 #define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
-#define             nDAT_CRC_FAIL  0x0       
 #define               CMD_TIMEOUT  0x4        /* CMD Time Out */
-#define              nCMD_TIMEOUT  0x0       
 #define               DAT_TIMEOUT  0x8        /* Data Time Out */
-#define              nDAT_TIMEOUT  0x0       
 #define               TX_UNDERRUN  0x10       /* Transmit Underrun */
-#define              nTX_UNDERRUN  0x0       
 #define                RX_OVERRUN  0x20       /* Receive Overrun */
-#define               nRX_OVERRUN  0x0       
 #define              CMD_RESP_END  0x40       /* CMD Response End */
-#define             nCMD_RESP_END  0x0       
 #define                  CMD_SENT  0x80       /* CMD Sent */
-#define                 nCMD_SENT  0x0       
 #define                   DAT_END  0x100      /* Data End */
-#define                  nDAT_END  0x0       
 #define             START_BIT_ERR  0x200      /* Start Bit Error */
-#define            nSTART_BIT_ERR  0x0       
 #define               DAT_BLK_END  0x400      /* Data Block End */
-#define              nDAT_BLK_END  0x0       
 #define                   CMD_ACT  0x800      /* CMD Active */
-#define                  nCMD_ACT  0x0       
 #define                    TX_ACT  0x1000     /* Transmit Active */
-#define                   nTX_ACT  0x0       
 #define                    RX_ACT  0x2000     /* Receive Active */
-#define                   nRX_ACT  0x0       
 #define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
-#define             nTX_FIFO_STAT  0x0       
 #define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
-#define             nRX_FIFO_STAT  0x0       
 #define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
-#define             nTX_FIFO_FULL  0x0       
 #define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
-#define             nRX_FIFO_FULL  0x0       
 #define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
-#define             nTX_FIFO_ZERO  0x0       
 #define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
-#define              nRX_DAT_ZERO  0x0       
 #define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
-#define               nTX_DAT_RDY  0x0       
 #define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
-#define              nRX_FIFO_RDY  0x0       
 
 /* Bit masks for SDH_STATUS_CLR */
 
 #define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
-#define        nCMD_CRC_FAIL_STAT  0x0       
 #define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
-#define        nDAT_CRC_FAIL_STAT  0x0       
 #define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
-#define         nCMD_TIMEOUT_STAT  0x0       
 #define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
-#define         nDAT_TIMEOUT_STAT  0x0       
 #define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
-#define         nTX_UNDERRUN_STAT  0x0       
 #define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
-#define          nRX_OVERRUN_STAT  0x0       
 #define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
-#define        nCMD_RESP_END_STAT  0x0       
 #define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
-#define            nCMD_SENT_STAT  0x0       
 #define              DAT_END_STAT  0x100      /* Data End Status */
-#define             nDAT_END_STAT  0x0       
 #define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
-#define       nSTART_BIT_ERR_STAT  0x0       
 #define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
-#define         nDAT_BLK_END_STAT  0x0       
 
 /* Bit masks for SDH_MASK0 */
 
 #define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
-#define        nCMD_CRC_FAIL_MASK  0x0       
 #define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
-#define        nDAT_CRC_FAIL_MASK  0x0       
 #define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
-#define         nCMD_TIMEOUT_MASK  0x0       
 #define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
-#define         nDAT_TIMEOUT_MASK  0x0       
 #define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
-#define         nTX_UNDERRUN_MASK  0x0       
 #define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
-#define          nRX_OVERRUN_MASK  0x0       
 #define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
-#define        nCMD_RESP_END_MASK  0x0       
 #define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
-#define            nCMD_SENT_MASK  0x0       
 #define              DAT_END_MASK  0x100      /* Data End Mask */
-#define             nDAT_END_MASK  0x0       
 #define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
-#define       nSTART_BIT_ERR_MASK  0x0       
 #define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
-#define         nDAT_BLK_END_MASK  0x0       
 #define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
-#define             nCMD_ACT_MASK  0x0       
 #define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
-#define              nTX_ACT_MASK  0x0       
 #define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
-#define              nRX_ACT_MASK  0x0       
 #define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
-#define        nTX_FIFO_STAT_MASK  0x0       
 #define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
-#define        nRX_FIFO_STAT_MASK  0x0       
 #define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
-#define        nTX_FIFO_FULL_MASK  0x0       
 #define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
-#define        nRX_FIFO_FULL_MASK  0x0       
 #define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
-#define        nTX_FIFO_ZERO_MASK  0x0       
 #define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
-#define         nRX_DAT_ZERO_MASK  0x0       
 #define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
-#define          nTX_DAT_RDY_MASK  0x0       
 #define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
-#define         nRX_FIFO_RDY_MASK  0x0       
 
 /* Bit masks for SDH_FIFO_CNT */
 
 /* Bit masks for SDH_E_STATUS */
 
 #define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
-#define             nSDIO_INT_DET  0x0       
 #define               SD_CARD_DET  0x10       /* SD Card Detect */
-#define              nSD_CARD_DET  0x0       
 
 /* Bit masks for SDH_E_MASK */
 
 #define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
-#define                 nSDIO_MSK  0x0       
 #define                   SCD_MSK  0x40       /* Mask Card Detect */
-#define                  nSCD_MSK  0x0       
 
 /* Bit masks for SDH_CFG */
 
 #define                   CLKS_EN  0x1        /* Clocks Enable */
-#define                  nCLKS_EN  0x0       
 #define                      SD4E  0x4        /* SDIO 4-Bit Enable */
-#define                     nSD4E  0x0       
 #define                       MWE  0x8        /* Moving Window Enable */
-#define                      nMWE  0x0       
 #define                    SD_RST  0x10       /* SDMMC Reset */
-#define                   nSD_RST  0x0       
 #define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
-#define                nPUP_SDDAT  0x0       
 #define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
-#define               nPUP_SDDAT3  0x0       
 #define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
-#define                nPD_SDDAT3  0x0       
 
 /* Bit masks for SDH_RD_WAIT_EN */
 
 #define                       RWR  0x1        /* Read Wait Request */
-#define                      nRWR  0x0       
 
 /* Bit masks for ATAPI_CONTROL */
 
 #define                 PIO_START  0x1        /* Start PIO/Reg Op */
-#define                nPIO_START  0x0       
 #define               MULTI_START  0x2        /* Start Multi-DMA Op */
-#define              nMULTI_START  0x0       
 #define               ULTRA_START  0x4        /* Start Ultra-DMA Op */
-#define              nULTRA_START  0x0       
 #define                  XFER_DIR  0x8        /* Transfer Direction */
-#define                 nXFER_DIR  0x0       
 #define                  IORDY_EN  0x10       /* IORDY Enable */
-#define                 nIORDY_EN  0x0       
 #define                FIFO_FLUSH  0x20       /* Flush FIFOs */
-#define               nFIFO_FLUSH  0x0       
 #define                  SOFT_RST  0x40       /* Soft Reset */
-#define                 nSOFT_RST  0x0       
 #define                   DEV_RST  0x80       /* Device Reset */
-#define                  nDEV_RST  0x0       
 #define                TFRCNT_RST  0x100      /* Trans Count Reset */
-#define               nTFRCNT_RST  0x0       
 #define               END_ON_TERM  0x200      /* End/Terminate Select */
-#define              nEND_ON_TERM  0x0       
 #define               PIO_USE_DMA  0x400      /* PIO-DMA Enable */
-#define              nPIO_USE_DMA  0x0       
 #define          UDMAIN_FIFO_THRS  0xf000     /* Ultra DMA-IN FIFO Threshold */
 
 /* Bit masks for ATAPI_STATUS */
 
 #define               PIO_XFER_ON  0x1        /* PIO transfer in progress */
-#define              nPIO_XFER_ON  0x0       
 #define             MULTI_XFER_ON  0x2        /* Multi-word DMA transfer in progress */
-#define            nMULTI_XFER_ON  0x0       
 #define             ULTRA_XFER_ON  0x4        /* Ultra DMA transfer in progress */
-#define            nULTRA_XFER_ON  0x0       
 #define               ULTRA_IN_FL  0xf0       /* Ultra DMA Input FIFO Level */
 
 /* Bit masks for ATAPI_DEV_ADDR */
 /* Bit masks for ATAPI_INT_MASK */
 
 #define        ATAPI_DEV_INT_MASK  0x1        /* Device interrupt mask */
-#define       nATAPI_DEV_INT_MASK  0x0       
 #define             PIO_DONE_MASK  0x2        /* PIO transfer done interrupt mask */
-#define            nPIO_DONE_MASK  0x0       
 #define           MULTI_DONE_MASK  0x4        /* Multi-DMA transfer done interrupt mask */
-#define          nMULTI_DONE_MASK  0x0       
 #define          UDMAIN_DONE_MASK  0x8        /* Ultra-DMA in transfer done interrupt mask */
-#define         nUDMAIN_DONE_MASK  0x0       
 #define         UDMAOUT_DONE_MASK  0x10       /* Ultra-DMA out transfer done interrupt mask */
-#define        nUDMAOUT_DONE_MASK  0x0       
 #define       HOST_TERM_XFER_MASK  0x20       /* Host terminate current transfer interrupt mask */
-#define      nHOST_TERM_XFER_MASK  0x0       
 #define           MULTI_TERM_MASK  0x40       /* Device terminate Multi-DMA transfer interrupt mask */
-#define          nMULTI_TERM_MASK  0x0       
 #define          UDMAIN_TERM_MASK  0x80       /* Device terminate Ultra-DMA-in transfer interrupt mask */
-#define         nUDMAIN_TERM_MASK  0x0       
 #define         UDMAOUT_TERM_MASK  0x100      /* Device terminate Ultra-DMA-out transfer interrupt mask */
-#define        nUDMAOUT_TERM_MASK  0x0       
 
 /* Bit masks for ATAPI_INT_STATUS */
 
 #define             ATAPI_DEV_INT  0x1        /* Device interrupt status */
-#define            nATAPI_DEV_INT  0x0       
 #define              PIO_DONE_INT  0x2        /* PIO transfer done interrupt status */
-#define             nPIO_DONE_INT  0x0       
 #define            MULTI_DONE_INT  0x4        /* Multi-DMA transfer done interrupt status */
-#define           nMULTI_DONE_INT  0x0       
 #define           UDMAIN_DONE_INT  0x8        /* Ultra-DMA in transfer done interrupt status */
-#define          nUDMAIN_DONE_INT  0x0       
 #define          UDMAOUT_DONE_INT  0x10       /* Ultra-DMA out transfer done interrupt status */
-#define         nUDMAOUT_DONE_INT  0x0       
 #define        HOST_TERM_XFER_INT  0x20       /* Host terminate current transfer interrupt status */
-#define       nHOST_TERM_XFER_INT  0x0       
 #define            MULTI_TERM_INT  0x40       /* Device terminate Multi-DMA transfer interrupt status */
-#define           nMULTI_TERM_INT  0x0       
 #define           UDMAIN_TERM_INT  0x80       /* Device terminate Ultra-DMA-in transfer interrupt status */
-#define          nUDMAIN_TERM_INT  0x0       
 #define          UDMAOUT_TERM_INT  0x100      /* Device terminate Ultra-DMA-out transfer interrupt status */
-#define         nUDMAOUT_TERM_INT  0x0       
 
 /* Bit masks for ATAPI_LINE_STATUS */
 
 #define                ATAPI_INTR  0x1        /* Device interrupt to host line status */
-#define               nATAPI_INTR  0x0       
 #define                ATAPI_DASP  0x2        /* Device dasp to host line status */
-#define               nATAPI_DASP  0x0       
 #define                ATAPI_CS0N  0x4        /* ATAPI chip select 0 line status */
-#define               nATAPI_CS0N  0x0       
 #define                ATAPI_CS1N  0x8        /* ATAPI chip select 1 line status */
-#define               nATAPI_CS1N  0x0       
 #define                ATAPI_ADDR  0x70       /* ATAPI address line status */
 #define              ATAPI_DMAREQ  0x80       /* ATAPI DMA request line status */
-#define             nATAPI_DMAREQ  0x0       
 #define             ATAPI_DMAACKN  0x100      /* ATAPI DMA acknowledge line status */
-#define            nATAPI_DMAACKN  0x0       
 #define               ATAPI_DIOWN  0x200      /* ATAPI write line status */
-#define              nATAPI_DIOWN  0x0       
 #define               ATAPI_DIORN  0x400      /* ATAPI read line status */
-#define              nATAPI_DIORN  0x0       
 #define               ATAPI_IORDY  0x800      /* ATAPI IORDY line status */
-#define              nATAPI_IORDY  0x0       
 
 /* Bit masks for ATAPI_SM_STATE */
 
 /* Bit masks for ATAPI_TERMINATE */
 
 #define           ATAPI_HOST_TERM  0x1        /* Host terminationation */
-#define          nATAPI_HOST_TERM  0x0       
 
 /* Bit masks for ATAPI_REG_TIM_0 */
 
 /* Bit masks for USB_POWER */
 
 #define           ENABLE_SUSPENDM  0x1        /* enable SuspendM output */
-#define          nENABLE_SUSPENDM  0x0       
 #define              SUSPEND_MODE  0x2        /* Suspend Mode indicator */
-#define             nSUSPEND_MODE  0x0       
 #define               RESUME_MODE  0x4        /* DMA Mode */
-#define              nRESUME_MODE  0x0       
 #define                     RESET  0x8        /* Reset indicator */
-#define                    nRESET  0x0       
 #define                   HS_MODE  0x10       /* High Speed mode indicator */
-#define                  nHS_MODE  0x0       
 #define                 HS_ENABLE  0x20       /* high Speed Enable */
-#define                nHS_ENABLE  0x0       
 #define                 SOFT_CONN  0x40       /* Soft connect */
-#define                nSOFT_CONN  0x0       
 #define                ISO_UPDATE  0x80       /* Isochronous update */
-#define               nISO_UPDATE  0x0       
 
 /* Bit masks for USB_INTRTX */
 
 #define                    EP0_TX  0x1        /* Tx Endpoint 0 interrupt */
-#define                   nEP0_TX  0x0       
 #define                    EP1_TX  0x2        /* Tx Endpoint 1 interrupt */
-#define                   nEP1_TX  0x0       
 #define                    EP2_TX  0x4        /* Tx Endpoint 2 interrupt */
-#define                   nEP2_TX  0x0       
 #define                    EP3_TX  0x8        /* Tx Endpoint 3 interrupt */
-#define                   nEP3_TX  0x0       
 #define                    EP4_TX  0x10       /* Tx Endpoint 4 interrupt */
-#define                   nEP4_TX  0x0       
 #define                    EP5_TX  0x20       /* Tx Endpoint 5 interrupt */
-#define                   nEP5_TX  0x0       
 #define                    EP6_TX  0x40       /* Tx Endpoint 6 interrupt */
-#define                   nEP6_TX  0x0       
 #define                    EP7_TX  0x80       /* Tx Endpoint 7 interrupt */
-#define                   nEP7_TX  0x0       
 
 /* Bit masks for USB_INTRRX */
 
 #define                    EP1_RX  0x2        /* Rx Endpoint 1 interrupt */
-#define                   nEP1_RX  0x0       
 #define                    EP2_RX  0x4        /* Rx Endpoint 2 interrupt */
-#define                   nEP2_RX  0x0       
 #define                    EP3_RX  0x8        /* Rx Endpoint 3 interrupt */
-#define                   nEP3_RX  0x0       
 #define                    EP4_RX  0x10       /* Rx Endpoint 4 interrupt */
-#define                   nEP4_RX  0x0       
 #define                    EP5_RX  0x20       /* Rx Endpoint 5 interrupt */
-#define                   nEP5_RX  0x0       
 #define                    EP6_RX  0x40       /* Rx Endpoint 6 interrupt */
-#define                   nEP6_RX  0x0       
 #define                    EP7_RX  0x80       /* Rx Endpoint 7 interrupt */
-#define                   nEP7_RX  0x0       
 
 /* Bit masks for USB_INTRTXE */
 
 #define                  EP0_TX_E  0x1        /* Endpoint 0 interrupt Enable */
-#define                 nEP0_TX_E  0x0       
 #define                  EP1_TX_E  0x2        /* Tx Endpoint 1 interrupt  Enable */
-#define                 nEP1_TX_E  0x0       
 #define                  EP2_TX_E  0x4        /* Tx Endpoint 2 interrupt  Enable */
-#define                 nEP2_TX_E  0x0       
 #define                  EP3_TX_E  0x8        /* Tx Endpoint 3 interrupt  Enable */
-#define                 nEP3_TX_E  0x0       
 #define                  EP4_TX_E  0x10       /* Tx Endpoint 4 interrupt  Enable */
-#define                 nEP4_TX_E  0x0       
 #define                  EP5_TX_E  0x20       /* Tx Endpoint 5 interrupt  Enable */
-#define                 nEP5_TX_E  0x0       
 #define                  EP6_TX_E  0x40       /* Tx Endpoint 6 interrupt  Enable */
-#define                 nEP6_TX_E  0x0       
 #define                  EP7_TX_E  0x80       /* Tx Endpoint 7 interrupt  Enable */
-#define                 nEP7_TX_E  0x0       
 
 /* Bit masks for USB_INTRRXE */
 
 #define                  EP1_RX_E  0x2        /* Rx Endpoint 1 interrupt  Enable */
-#define                 nEP1_RX_E  0x0       
 #define                  EP2_RX_E  0x4        /* Rx Endpoint 2 interrupt  Enable */
-#define                 nEP2_RX_E  0x0       
 #define                  EP3_RX_E  0x8        /* Rx Endpoint 3 interrupt  Enable */
-#define                 nEP3_RX_E  0x0       
 #define                  EP4_RX_E  0x10       /* Rx Endpoint 4 interrupt  Enable */
-#define                 nEP4_RX_E  0x0       
 #define                  EP5_RX_E  0x20       /* Rx Endpoint 5 interrupt  Enable */
-#define                 nEP5_RX_E  0x0       
 #define                  EP6_RX_E  0x40       /* Rx Endpoint 6 interrupt  Enable */
-#define                 nEP6_RX_E  0x0       
 #define                  EP7_RX_E  0x80       /* Rx Endpoint 7 interrupt  Enable */
-#define                 nEP7_RX_E  0x0       
 
 /* Bit masks for USB_INTRUSB */
 
 #define                 SUSPEND_B  0x1        /* Suspend indicator */
-#define                nSUSPEND_B  0x0       
 #define                  RESUME_B  0x2        /* Resume indicator */
-#define                 nRESUME_B  0x0       
 #define          RESET_OR_BABLE_B  0x4        /* Reset/babble indicator */
-#define         nRESET_OR_BABLE_B  0x0       
 #define                     SOF_B  0x8        /* Start of frame */
-#define                    nSOF_B  0x0       
 #define                    CONN_B  0x10       /* Connection indicator */
-#define                   nCONN_B  0x0       
 #define                  DISCON_B  0x20       /* Disconnect indicator */
-#define                 nDISCON_B  0x0       
 #define             SESSION_REQ_B  0x40       /* Session Request */
-#define            nSESSION_REQ_B  0x0       
 #define              VBUS_ERROR_B  0x80       /* Vbus threshold indicator */
-#define             nVBUS_ERROR_B  0x0       
 
 /* Bit masks for USB_INTRUSBE */
 
 #define                SUSPEND_BE  0x1        /* Suspend indicator int enable */
-#define               nSUSPEND_BE  0x0       
 #define                 RESUME_BE  0x2        /* Resume indicator int enable */
-#define                nRESUME_BE  0x0       
 #define         RESET_OR_BABLE_BE  0x4        /* Reset/babble indicator int enable */
-#define        nRESET_OR_BABLE_BE  0x0       
 #define                    SOF_BE  0x8        /* Start of frame int enable */
-#define                   nSOF_BE  0x0       
 #define                   CONN_BE  0x10       /* Connection indicator int enable */
-#define                  nCONN_BE  0x0       
 #define                 DISCON_BE  0x20       /* Disconnect indicator int enable */
-#define                nDISCON_BE  0x0       
 #define            SESSION_REQ_BE  0x40       /* Session Request int enable */
-#define           nSESSION_REQ_BE  0x0       
 #define             VBUS_ERROR_BE  0x80       /* Vbus threshold indicator int enable */
-#define            nVBUS_ERROR_BE  0x0       
 
 /* Bit masks for USB_FRAME */
 
 /* Bit masks for USB_GLOBAL_CTL */
 
 #define                GLOBAL_ENA  0x1        /* enables USB module */
-#define               nGLOBAL_ENA  0x0       
 #define                EP1_TX_ENA  0x2        /* Transmit endpoint 1 enable */
-#define               nEP1_TX_ENA  0x0       
 #define                EP2_TX_ENA  0x4        /* Transmit endpoint 2 enable */
-#define               nEP2_TX_ENA  0x0       
 #define                EP3_TX_ENA  0x8        /* Transmit endpoint 3 enable */
-#define               nEP3_TX_ENA  0x0       
 #define                EP4_TX_ENA  0x10       /* Transmit endpoint 4 enable */
-#define               nEP4_TX_ENA  0x0       
 #define                EP5_TX_ENA  0x20       /* Transmit endpoint 5 enable */
-#define               nEP5_TX_ENA  0x0       
 #define                EP6_TX_ENA  0x40       /* Transmit endpoint 6 enable */
-#define               nEP6_TX_ENA  0x0       
 #define                EP7_TX_ENA  0x80       /* Transmit endpoint 7 enable */
-#define               nEP7_TX_ENA  0x0       
 #define                EP1_RX_ENA  0x100      /* Receive endpoint 1 enable */
-#define               nEP1_RX_ENA  0x0       
 #define                EP2_RX_ENA  0x200      /* Receive endpoint 2 enable */
-#define               nEP2_RX_ENA  0x0       
 #define                EP3_RX_ENA  0x400      /* Receive endpoint 3 enable */
-#define               nEP3_RX_ENA  0x0       
 #define                EP4_RX_ENA  0x800      /* Receive endpoint 4 enable */
-#define               nEP4_RX_ENA  0x0       
 #define                EP5_RX_ENA  0x1000     /* Receive endpoint 5 enable */
-#define               nEP5_RX_ENA  0x0       
 #define                EP6_RX_ENA  0x2000     /* Receive endpoint 6 enable */
-#define               nEP6_RX_ENA  0x0       
 #define                EP7_RX_ENA  0x4000     /* Receive endpoint 7 enable */
-#define               nEP7_RX_ENA  0x0       
 
 /* Bit masks for USB_OTG_DEV_CTL */
 
 #define                   SESSION  0x1        /* session indicator */
-#define                  nSESSION  0x0       
 #define                  HOST_REQ  0x2        /* Host negotiation request */
-#define                 nHOST_REQ  0x0       
 #define                 HOST_MODE  0x4        /* indicates USBDRC is a host */
-#define                nHOST_MODE  0x0       
 #define                     VBUS0  0x8        /* Vbus level indicator[0] */
-#define                    nVBUS0  0x0       
 #define                     VBUS1  0x10       /* Vbus level indicator[1] */
-#define                    nVBUS1  0x0       
 #define                     LSDEV  0x20       /* Low-speed indicator */
-#define                    nLSDEV  0x0       
 #define                     FSDEV  0x40       /* Full or High-speed indicator */
-#define                    nFSDEV  0x0       
 #define                  B_DEVICE  0x80       /* A' or 'B' device indicator */
-#define                 nB_DEVICE  0x0       
 
 /* Bit masks for USB_OTG_VBUS_IRQ */
 
 #define             DRIVE_VBUS_ON  0x1        /* indicator to drive VBUS control circuit */
-#define            nDRIVE_VBUS_ON  0x0       
 #define            DRIVE_VBUS_OFF  0x2        /* indicator to shut off charge pump */
-#define           nDRIVE_VBUS_OFF  0x0       
 #define           CHRG_VBUS_START  0x4        /* indicator for external circuit to start charging VBUS */
-#define          nCHRG_VBUS_START  0x0       
 #define             CHRG_VBUS_END  0x8        /* indicator for external circuit to end charging VBUS */
-#define            nCHRG_VBUS_END  0x0       
 #define        DISCHRG_VBUS_START  0x10       /* indicator to start discharging VBUS */
-#define       nDISCHRG_VBUS_START  0x0       
 #define          DISCHRG_VBUS_END  0x20       /* indicator to stop discharging VBUS */
-#define         nDISCHRG_VBUS_END  0x0       
 
 /* Bit masks for USB_OTG_VBUS_MASK */
 
 #define         DRIVE_VBUS_ON_ENA  0x1        /* enable DRIVE_VBUS_ON interrupt */
-#define        nDRIVE_VBUS_ON_ENA  0x0       
 #define        DRIVE_VBUS_OFF_ENA  0x2        /* enable DRIVE_VBUS_OFF interrupt */
-#define       nDRIVE_VBUS_OFF_ENA  0x0       
 #define       CHRG_VBUS_START_ENA  0x4        /* enable CHRG_VBUS_START interrupt */
-#define      nCHRG_VBUS_START_ENA  0x0       
 #define         CHRG_VBUS_END_ENA  0x8        /* enable CHRG_VBUS_END interrupt */
-#define        nCHRG_VBUS_END_ENA  0x0       
 #define    DISCHRG_VBUS_START_ENA  0x10       /* enable DISCHRG_VBUS_START interrupt */
-#define   nDISCHRG_VBUS_START_ENA  0x0       
 #define      DISCHRG_VBUS_END_ENA  0x20       /* enable DISCHRG_VBUS_END interrupt */
-#define     nDISCHRG_VBUS_END_ENA  0x0       
 
 /* Bit masks for USB_CSR0 */
 
 #define                  RXPKTRDY  0x1        /* data packet receive indicator */
-#define                 nRXPKTRDY  0x0       
 #define                  TXPKTRDY  0x2        /* data packet in FIFO indicator */
-#define                 nTXPKTRDY  0x0       
 #define                STALL_SENT  0x4        /* STALL handshake sent */
-#define               nSTALL_SENT  0x0       
 #define                   DATAEND  0x8        /* Data end indicator */
-#define                  nDATAEND  0x0       
 #define                  SETUPEND  0x10       /* Setup end */
-#define                 nSETUPEND  0x0       
 #define                 SENDSTALL  0x20       /* Send STALL handshake */
-#define                nSENDSTALL  0x0       
 #define         SERVICED_RXPKTRDY  0x40       /* used to clear the RxPktRdy bit */
-#define        nSERVICED_RXPKTRDY  0x0       
 #define         SERVICED_SETUPEND  0x80       /* used to clear the SetupEnd bit */
-#define        nSERVICED_SETUPEND  0x0       
 #define                 FLUSHFIFO  0x100      /* flush endpoint FIFO */
-#define                nFLUSHFIFO  0x0       
 #define          STALL_RECEIVED_H  0x4        /* STALL handshake received host mode */
-#define         nSTALL_RECEIVED_H  0x0       
 #define                SETUPPKT_H  0x8        /* send Setup token host mode */
-#define               nSETUPPKT_H  0x0       
 #define                   ERROR_H  0x10       /* timeout error indicator host mode */
-#define                  nERROR_H  0x0       
 #define                  REQPKT_H  0x20       /* Request an IN transaction host mode */
-#define                 nREQPKT_H  0x0       
 #define               STATUSPKT_H  0x40       /* Status stage transaction host mode */
-#define              nSTATUSPKT_H  0x0       
 #define             NAK_TIMEOUT_H  0x80       /* EP0 halted after a NAK host mode */
-#define            nNAK_TIMEOUT_H  0x0       
 
 /* Bit masks for USB_COUNT0 */
 
 /* Bit masks for USB_TXCSR */
 
 #define                TXPKTRDY_T  0x1        /* data packet in FIFO indicator */
-#define               nTXPKTRDY_T  0x0       
 #define          FIFO_NOT_EMPTY_T  0x2        /* FIFO not empty */
-#define         nFIFO_NOT_EMPTY_T  0x0       
 #define                UNDERRUN_T  0x4        /* TxPktRdy not set  for an IN token */
-#define               nUNDERRUN_T  0x0       
 #define               FLUSHFIFO_T  0x8        /* flush endpoint FIFO */
-#define              nFLUSHFIFO_T  0x0       
 #define              STALL_SEND_T  0x10       /* issue a Stall handshake */
-#define             nSTALL_SEND_T  0x0       
 #define              STALL_SENT_T  0x20       /* Stall handshake transmitted */
-#define             nSTALL_SENT_T  0x0       
 #define        CLEAR_DATATOGGLE_T  0x40       /* clear endpoint data toggle */
-#define       nCLEAR_DATATOGGLE_T  0x0       
 #define                INCOMPTX_T  0x80       /* indicates that a large packet is split */
-#define               nINCOMPTX_T  0x0       
 #define              DMAREQMODE_T  0x400      /* DMA mode (0 or 1) selection */
-#define             nDMAREQMODE_T  0x0       
 #define        FORCE_DATATOGGLE_T  0x800      /* Force data toggle */
-#define       nFORCE_DATATOGGLE_T  0x0       
 #define              DMAREQ_ENA_T  0x1000     /* Enable DMA request for Tx EP */
-#define             nDMAREQ_ENA_T  0x0       
 #define                     ISO_T  0x4000     /* enable Isochronous transfers */
-#define                    nISO_T  0x0       
 #define                 AUTOSET_T  0x8000     /* allows TxPktRdy to be set automatically */
-#define                nAUTOSET_T  0x0       
 #define                  ERROR_TH  0x4        /* error condition host mode */
-#define                 nERROR_TH  0x0       
 #define         STALL_RECEIVED_TH  0x20       /* Stall handshake received host mode */
-#define        nSTALL_RECEIVED_TH  0x0       
 #define            NAK_TIMEOUT_TH  0x80       /* NAK timeout host mode */
-#define           nNAK_TIMEOUT_TH  0x0       
 
 /* Bit masks for USB_TXCOUNT */
 
 /* Bit masks for USB_RXCSR */
 
 #define                RXPKTRDY_R  0x1        /* data packet in FIFO indicator */
-#define               nRXPKTRDY_R  0x0       
 #define               FIFO_FULL_R  0x2        /* FIFO not empty */
-#define              nFIFO_FULL_R  0x0       
 #define                 OVERRUN_R  0x4        /* TxPktRdy not set  for an IN token */
-#define                nOVERRUN_R  0x0       
 #define               DATAERROR_R  0x8        /* Out packet cannot be loaded into Rx  FIFO */
-#define              nDATAERROR_R  0x0       
 #define               FLUSHFIFO_R  0x10       /* flush endpoint FIFO */
-#define              nFLUSHFIFO_R  0x0       
 #define              STALL_SEND_R  0x20       /* issue a Stall handshake */
-#define             nSTALL_SEND_R  0x0       
 #define              STALL_SENT_R  0x40       /* Stall handshake transmitted */
-#define             nSTALL_SENT_R  0x0       
 #define        CLEAR_DATATOGGLE_R  0x80       /* clear endpoint data toggle */
-#define       nCLEAR_DATATOGGLE_R  0x0       
 #define                INCOMPRX_R  0x100      /* indicates that a large packet is split */
-#define               nINCOMPRX_R  0x0       
 #define              DMAREQMODE_R  0x800      /* DMA mode (0 or 1) selection */
-#define             nDMAREQMODE_R  0x0       
 #define                 DISNYET_R  0x1000     /* disable Nyet handshakes */
-#define                nDISNYET_R  0x0       
 #define              DMAREQ_ENA_R  0x2000     /* Enable DMA request for Tx EP */
-#define             nDMAREQ_ENA_R  0x0       
 #define                     ISO_R  0x4000     /* enable Isochronous transfers */
-#define                    nISO_R  0x0       
 #define               AUTOCLEAR_R  0x8000     /* allows TxPktRdy to be set automatically */
-#define              nAUTOCLEAR_R  0x0       
 #define                  ERROR_RH  0x4        /* TxPktRdy not set  for an IN token host mode */
-#define                 nERROR_RH  0x0       
 #define                 REQPKT_RH  0x20       /* request an IN transaction host mode */
-#define                nREQPKT_RH  0x0       
 #define         STALL_RECEIVED_RH  0x40       /* Stall handshake received host mode */
-#define        nSTALL_RECEIVED_RH  0x0       
 #define               INCOMPRX_RH  0x100      /* indicates that a large packet is split host mode */
-#define              nINCOMPRX_RH  0x0       
 #define             DMAREQMODE_RH  0x800      /* DMA mode (0 or 1) selection host mode */
-#define            nDMAREQMODE_RH  0x0       
 #define                AUTOREQ_RH  0x4000     /* sets ReqPkt automatically host mode */
-#define               nAUTOREQ_RH  0x0       
 
 /* Bit masks for USB_RXCOUNT */
 
 /* Bit masks for USB_DMA_INTERRUPT */
 
 #define                  DMA0_INT  0x1        /* DMA0 pending interrupt */
-#define                 nDMA0_INT  0x0       
 #define                  DMA1_INT  0x2        /* DMA1 pending interrupt */
-#define                 nDMA1_INT  0x0       
 #define                  DMA2_INT  0x4        /* DMA2 pending interrupt */
-#define                 nDMA2_INT  0x0       
 #define                  DMA3_INT  0x8        /* DMA3 pending interrupt */
-#define                 nDMA3_INT  0x0       
 #define                  DMA4_INT  0x10       /* DMA4 pending interrupt */
-#define                 nDMA4_INT  0x0       
 #define                  DMA5_INT  0x20       /* DMA5 pending interrupt */
-#define                 nDMA5_INT  0x0       
 #define                  DMA6_INT  0x40       /* DMA6 pending interrupt */
-#define                 nDMA6_INT  0x0       
 #define                  DMA7_INT  0x80       /* DMA7 pending interrupt */
-#define                 nDMA7_INT  0x0       
 
 /* Bit masks for USB_DMAxCONTROL */
 
 #define                   DMA_ENA  0x1        /* DMA enable */
-#define                  nDMA_ENA  0x0       
 #define                 DIRECTION  0x2        /* direction of DMA transfer */
-#define                nDIRECTION  0x0       
 #define                      MODE  0x4        /* DMA Bus error */
-#define                     nMODE  0x0       
 #define                   INT_ENA  0x8        /* Interrupt enable */
-#define                  nINT_ENA  0x0       
 #define                     EPNUM  0xf0       /* EP number */
 #define                  BUSERROR  0x100      /* DMA Bus error */
-#define                 nBUSERROR  0x0       
 
 /* Bit masks for USB_DMAxADDRHIGH */
 
index 8fc77ea12aa91a6bd16cb8c90c92f603d9adda0c..dd955dcd39b8949cb4aafd20e52b333c80386b32 100644 (file)
 /* Bit masks for PIXC_CTL */
 
 #define                   PIXC_EN  0x1        /* Pixel Compositor Enable */
-#define                  nPIXC_EN  0x0       
 #define                  OVR_A_EN  0x2        /* Overlay A Enable */
-#define                 nOVR_A_EN  0x0       
 #define                  OVR_B_EN  0x4        /* Overlay B Enable */
-#define                 nOVR_B_EN  0x0       
 #define                  IMG_FORM  0x8        /* Image Data Format */
-#define                 nIMG_FORM  0x0       
 #define                  OVR_FORM  0x10       /* Overlay Data Format */
-#define                 nOVR_FORM  0x0       
 #define                  OUT_FORM  0x20       /* Output Data Format */
-#define                 nOUT_FORM  0x0       
 #define                   UDS_MOD  0x40       /* Resampling Mode */
-#define                  nUDS_MOD  0x0       
 #define                     TC_EN  0x80       /* Transparent Color Enable */
-#define                    nTC_EN  0x0       
 #define                  IMG_STAT  0x300      /* Image FIFO Status */
 #define                  OVR_STAT  0xc00      /* Overlay FIFO Status */
 #define                    WM_LVL  0x3000     /* FIFO Watermark Level */
 /* Bit masks for PIXC_INTRSTAT */
 
 #define                OVR_INT_EN  0x1        /* Interrupt at End of Last Valid Overlay */
-#define               nOVR_INT_EN  0x0       
 #define                FRM_INT_EN  0x2        /* Interrupt at End of Frame */
-#define               nFRM_INT_EN  0x0       
 #define              OVR_INT_STAT  0x4        /* Overlay Interrupt Status */
-#define             nOVR_INT_STAT  0x0       
 #define              FRM_INT_STAT  0x8        /* Frame Interrupt Status */
-#define             nFRM_INT_STAT  0x0       
 
 /* Bit masks for PIXC_RYCON */
 
 #define                       A12  0xffc00    /* A12 in the Coefficient Matrix */
 #define                       A13  0x3ff00000 /* A13 in the Coefficient Matrix */
 #define                  RY_MULT4  0x40000000 /* Multiply Row by 4 */
-#define                 nRY_MULT4  0x0       
 
 /* Bit masks for PIXC_GUCON */
 
 #define                       A22  0xffc00    /* A22 in the Coefficient Matrix */
 #define                       A23  0x3ff00000 /* A23 in the Coefficient Matrix */
 #define                  GU_MULT4  0x40000000 /* Multiply Row by 4 */
-#define                 nGU_MULT4  0x0       
 
 /* Bit masks for PIXC_BVCON */
 
 #define                       A32  0xffc00    /* A32 in the Coefficient Matrix */
 #define                       A33  0x3ff00000 /* A33 in the Coefficient Matrix */
 #define                  BV_MULT4  0x40000000 /* Multiply Row by 4 */
-#define                 nBV_MULT4  0x0       
 
 /* Bit masks for PIXC_CCBIAS */
 
 /* Bit masks for HOST_CONTROL */
 
 #define                   HOST_EN  0x1        /* Host Enable */
-#define                  nHOST_EN  0x0       
 #define                  HOST_END  0x2        /* Host Endianess */
-#define                 nHOST_END  0x0       
 #define                 DATA_SIZE  0x4        /* Data Size */
-#define                nDATA_SIZE  0x0       
 #define                  HOST_RST  0x8        /* Host Reset */
-#define                 nHOST_RST  0x0       
 #define                  HRDY_OVR  0x20       /* Host Ready Override */
-#define                 nHRDY_OVR  0x0       
 #define                  INT_MODE  0x40       /* Interrupt Mode */
-#define                 nINT_MODE  0x0       
 #define                     BT_EN  0x80       /* Bus Timeout Enable */
-#define                    nBT_EN  0x0       
 #define                       EHW  0x100      /* Enable Host Write */
-#define                      nEHW  0x0       
 #define                       EHR  0x200      /* Enable Host Read */
-#define                      nEHR  0x0       
 #define                       BDR  0x400      /* Burst DMA Requests */
-#define                      nBDR  0x0       
 
 /* Bit masks for HOST_STATUS */
 
 #define                     READY  0x1        /* DMA Ready */
-#define                    nREADY  0x0       
 #define                  FIFOFULL  0x2        /* FIFO Full */
-#define                 nFIFOFULL  0x0       
 #define                 FIFOEMPTY  0x4        /* FIFO Empty */
-#define                nFIFOEMPTY  0x0       
 #define                  COMPLETE  0x8        /* DMA Complete */
-#define                 nCOMPLETE  0x0       
 #define                      HSHK  0x10       /* Host Handshake */
-#define                     nHSHK  0x0       
 #define                   TIMEOUT  0x20       /* Host Timeout */
-#define                  nTIMEOUT  0x0       
 #define                      HIRQ  0x40       /* Host Interrupt Request */
-#define                     nHIRQ  0x0       
 #define                ALLOW_CNFG  0x80       /* Allow New Configuration */
-#define               nALLOW_CNFG  0x0       
 #define                   DMA_DIR  0x100      /* DMA Direction */
-#define                  nDMA_DIR  0x0       
 #define                       BTE  0x200      /* Bus Timeout Enabled */
-#define                      nBTE  0x0       
 
 /* Bit masks for HOST_TIMEOUT */
 
 /* Bit masks for TIMER_ENABLE1 */
 
 #define                    TIMEN8  0x1        /* Timer 8 Enable */
-#define                   nTIMEN8  0x0       
 #define                    TIMEN9  0x2        /* Timer 9 Enable */
-#define                   nTIMEN9  0x0       
 #define                   TIMEN10  0x4        /* Timer 10 Enable */
-#define                  nTIMEN10  0x0       
 
 /* Bit masks for TIMER_DISABLE1 */
 
 #define                   TIMDIS8  0x1        /* Timer 8 Disable */
-#define                  nTIMDIS8  0x0       
 #define                   TIMDIS9  0x2        /* Timer 9 Disable */
-#define                  nTIMDIS9  0x0       
 #define                  TIMDIS10  0x4        /* Timer 10 Disable */
-#define                 nTIMDIS10  0x0       
 
 /* Bit masks for TIMER_STATUS1 */
 
 #define                    TIMIL8  0x1        /* Timer 8 Interrupt */
-#define                   nTIMIL8  0x0       
 #define                    TIMIL9  0x2        /* Timer 9 Interrupt */
-#define                   nTIMIL9  0x0       
 #define                   TIMIL10  0x4        /* Timer 10 Interrupt */
-#define                  nTIMIL10  0x0       
 #define                 TOVF_ERR8  0x10       /* Timer 8 Counter Overflow */
-#define                nTOVF_ERR8  0x0       
 #define                 TOVF_ERR9  0x20       /* Timer 9 Counter Overflow */
-#define                nTOVF_ERR9  0x0       
 #define                TOVF_ERR10  0x40       /* Timer 10 Counter Overflow */
-#define               nTOVF_ERR10  0x0       
 #define                     TRUN8  0x1000     /* Timer 8 Slave Enable Status */
-#define                    nTRUN8  0x0       
 #define                     TRUN9  0x2000     /* Timer 9 Slave Enable Status */
-#define                    nTRUN9  0x0       
 #define                    TRUN10  0x4000     /* Timer 10 Slave Enable Status */
-#define                   nTRUN10  0x0       
 
 /* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
 
 /* Bit masks for HMDMAx_CONTROL */
 
 #define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
-#define                  nHMDMAEN  0x0       
 #define                       REP  0x2        /* Handshake MDMA Request Polarity */
-#define                      nREP  0x0       
 #define                       UTE  0x8        /* Urgency Threshold Enable */
-#define                      nUTE  0x0       
 #define                       OIE  0x10       /* Overflow Interrupt Enable */
-#define                      nOIE  0x0       
 #define                      BDIE  0x20       /* Block Done Interrupt Enable */
-#define                     nBDIE  0x0       
 #define                      MBDI  0x40       /* Mask Block Done Interrupt */
-#define                     nMBDI  0x0       
 #define                       DRQ  0x300      /* Handshake MDMA Request Type */
 #define                       RBC  0x1000     /* Force Reload of BCOUNT */
-#define                      nRBC  0x0       
 #define                        PS  0x2000     /* Pin Status */
-#define                       nPS  0x0       
 #define                        OI  0x4000     /* Overflow Interrupt Generated */
-#define                       nOI  0x0       
 #define                       BDI  0x8000     /* Block Done Interrupt Generated */
-#define                      nBDI  0x0       
 
 /* ******************************************* */
 /*     MULTI BIT MACRO ENUMERATIONS            */
index d9e3062a9117d061e97482c95b65fab8870d0cea..8d4214e0807ccac3d58b90b5ae277f5b21569d9a 100644 (file)
 /* Bit masks for PIXC_CTL */
 
 #define                   PIXC_EN  0x1        /* Pixel Compositor Enable */
-#define                  nPIXC_EN  0x0       
 #define                  OVR_A_EN  0x2        /* Overlay A Enable */
-#define                 nOVR_A_EN  0x0       
 #define                  OVR_B_EN  0x4        /* Overlay B Enable */
-#define                 nOVR_B_EN  0x0       
 #define                  IMG_FORM  0x8        /* Image Data Format */
-#define                 nIMG_FORM  0x0       
 #define                  OVR_FORM  0x10       /* Overlay Data Format */
-#define                 nOVR_FORM  0x0       
 #define                  OUT_FORM  0x20       /* Output Data Format */
-#define                 nOUT_FORM  0x0       
 #define                   UDS_MOD  0x40       /* Resampling Mode */
-#define                  nUDS_MOD  0x0       
 #define                     TC_EN  0x80       /* Transparent Color Enable */
-#define                    nTC_EN  0x0       
 #define                  IMG_STAT  0x300      /* Image FIFO Status */
 #define                  OVR_STAT  0xc00      /* Overlay FIFO Status */
 #define                    WM_LVL  0x3000     /* FIFO Watermark Level */
 /* Bit masks for PIXC_INTRSTAT */
 
 #define                OVR_INT_EN  0x1        /* Interrupt at End of Last Valid Overlay */
-#define               nOVR_INT_EN  0x0       
 #define                FRM_INT_EN  0x2        /* Interrupt at End of Frame */
-#define               nFRM_INT_EN  0x0       
 #define              OVR_INT_STAT  0x4        /* Overlay Interrupt Status */
-#define             nOVR_INT_STAT  0x0       
 #define              FRM_INT_STAT  0x8        /* Frame Interrupt Status */
-#define             nFRM_INT_STAT  0x0       
 
 /* Bit masks for PIXC_RYCON */
 
 #define                       A12  0xffc00    /* A12 in the Coefficient Matrix */
 #define                       A13  0x3ff00000 /* A13 in the Coefficient Matrix */
 #define                  RY_MULT4  0x40000000 /* Multiply Row by 4 */
-#define                 nRY_MULT4  0x0       
 
 /* Bit masks for PIXC_GUCON */
 
 #define                       A22  0xffc00    /* A22 in the Coefficient Matrix */
 #define                       A23  0x3ff00000 /* A23 in the Coefficient Matrix */
 #define                  GU_MULT4  0x40000000 /* Multiply Row by 4 */
-#define                 nGU_MULT4  0x0       
 
 /* Bit masks for PIXC_BVCON */
 
 #define                       A32  0xffc00    /* A32 in the Coefficient Matrix */
 #define                       A33  0x3ff00000 /* A33 in the Coefficient Matrix */
 #define                  BV_MULT4  0x40000000 /* Multiply Row by 4 */
-#define                 nBV_MULT4  0x0       
 
 /* Bit masks for PIXC_CCBIAS */
 
 /* Bit masks for HOST_CONTROL */
 
 #define                   HOST_EN  0x1        /* Host Enable */
-#define                  nHOST_EN  0x0       
 #define                  HOST_END  0x2        /* Host Endianess */
-#define                 nHOST_END  0x0       
 #define                 DATA_SIZE  0x4        /* Data Size */
-#define                nDATA_SIZE  0x0       
 #define                  HOST_RST  0x8        /* Host Reset */
-#define                 nHOST_RST  0x0       
 #define                  HRDY_OVR  0x20       /* Host Ready Override */
-#define                 nHRDY_OVR  0x0       
 #define                  INT_MODE  0x40       /* Interrupt Mode */
-#define                 nINT_MODE  0x0       
 #define                     BT_EN  0x80       /* Bus Timeout Enable */
-#define                    nBT_EN  0x0       
 #define                       EHW  0x100      /* Enable Host Write */
-#define                      nEHW  0x0       
 #define                       EHR  0x200      /* Enable Host Read */
-#define                      nEHR  0x0       
 #define                       BDR  0x400      /* Burst DMA Requests */
-#define                      nBDR  0x0       
 
 /* Bit masks for HOST_STATUS */
 
 #define                     READY  0x1        /* DMA Ready */
-#define                    nREADY  0x0       
 #define                  FIFOFULL  0x2        /* FIFO Full */
-#define                 nFIFOFULL  0x0       
 #define                 FIFOEMPTY  0x4        /* FIFO Empty */
-#define                nFIFOEMPTY  0x0       
 #define                  COMPLETE  0x8        /* DMA Complete */
-#define                 nCOMPLETE  0x0       
 #define                      HSHK  0x10       /* Host Handshake */
-#define                     nHSHK  0x0       
 #define                   TIMEOUT  0x20       /* Host Timeout */
-#define                  nTIMEOUT  0x0       
 #define                      HIRQ  0x40       /* Host Interrupt Request */
-#define                     nHIRQ  0x0       
 #define                ALLOW_CNFG  0x80       /* Allow New Configuration */
-#define               nALLOW_CNFG  0x0       
 #define                   DMA_DIR  0x100      /* DMA Direction */
-#define                  nDMA_DIR  0x0       
 #define                       BTE  0x200      /* Bus Timeout Enabled */
-#define                      nBTE  0x0       
 
 /* Bit masks for HOST_TIMEOUT */
 
 /* Bit masks for KPAD_CTL */
 
 #define                   KPAD_EN  0x1        /* Keypad Enable */
-#define                  nKPAD_EN  0x0       
 #define              KPAD_IRQMODE  0x6        /* Key Press Interrupt Enable */
 #define                KPAD_ROWEN  0x1c00     /* Row Enable Width */
 #define                KPAD_COLEN  0xe000     /* Column Enable Width */
 /* Bit masks for KPAD_STAT */
 
 #define                  KPAD_IRQ  0x1        /* Keypad Interrupt Status */
-#define                 nKPAD_IRQ  0x0       
 #define              KPAD_MROWCOL  0x6        /* Multiple Row/Column Keypress Status */
 #define              KPAD_PRESSED  0x8        /* Key press current status */
-#define             nKPAD_PRESSED  0x0       
 
 /* Bit masks for KPAD_SOFTEVAL */
 
 #define           KPAD_SOFTEVAL_E  0x2        /* Software Programmable Force Evaluate */
-#define          nKPAD_SOFTEVAL_E  0x0       
 
 /* Bit masks for SDH_COMMAND */
 
 #define                   CMD_IDX  0x3f       /* Command Index */
 #define                   CMD_RSP  0x40       /* Response */
-#define                  nCMD_RSP  0x0       
 #define                 CMD_L_RSP  0x80       /* Long Response */
-#define                nCMD_L_RSP  0x0       
 #define                 CMD_INT_E  0x100      /* Command Interrupt */
-#define                nCMD_INT_E  0x0       
 #define                CMD_PEND_E  0x200      /* Command Pending */
-#define               nCMD_PEND_E  0x0       
 #define                     CMD_E  0x400      /* Command Enable */
-#define                    nCMD_E  0x0       
 
 /* Bit masks for SDH_PWR_CTL */
 
 #define                       TBD  0x3c       /* TBD */
 #endif
 #define                 SD_CMD_OD  0x40       /* Open Drain Output */
-#define                nSD_CMD_OD  0x0       
 #define                   ROD_CTL  0x80       /* Rod Control */
-#define                  nROD_CTL  0x0       
 
 /* Bit masks for SDH_CLK_CTL */
 
 #define                    CLKDIV  0xff       /* MC_CLK Divisor */
 #define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
-#define                    nCLK_E  0x0       
 #define                  PWR_SV_E  0x200      /* Power Save Enable */
-#define                 nPWR_SV_E  0x0       
 #define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
-#define            nCLKDIV_BYPASS  0x0       
 #define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
-#define                 nWIDE_BUS  0x0       
 
 /* Bit masks for SDH_RESP_CMD */
 
 /* Bit masks for SDH_DATA_CTL */
 
 #define                     DTX_E  0x1        /* Data Transfer Enable */
-#define                    nDTX_E  0x0       
 #define                   DTX_DIR  0x2        /* Data Transfer Direction */
-#define                  nDTX_DIR  0x0       
 #define                  DTX_MODE  0x4        /* Data Transfer Mode */
-#define                 nDTX_MODE  0x0       
 #define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
-#define                nDTX_DMA_E  0x0       
 #define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
 
 /* Bit masks for SDH_STATUS */
 
 #define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
-#define             nCMD_CRC_FAIL  0x0       
 #define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
-#define             nDAT_CRC_FAIL  0x0       
 #define               CMD_TIMEOUT  0x4        /* CMD Time Out */
-#define              nCMD_TIMEOUT  0x0       
 #define               DAT_TIMEOUT  0x8        /* Data Time Out */
-#define              nDAT_TIMEOUT  0x0       
 #define               TX_UNDERRUN  0x10       /* Transmit Underrun */
-#define              nTX_UNDERRUN  0x0       
 #define                RX_OVERRUN  0x20       /* Receive Overrun */
-#define               nRX_OVERRUN  0x0       
 #define              CMD_RESP_END  0x40       /* CMD Response End */
-#define             nCMD_RESP_END  0x0       
 #define                  CMD_SENT  0x80       /* CMD Sent */
-#define                 nCMD_SENT  0x0       
 #define                   DAT_END  0x100      /* Data End */
-#define                  nDAT_END  0x0       
 #define             START_BIT_ERR  0x200      /* Start Bit Error */
-#define            nSTART_BIT_ERR  0x0       
 #define               DAT_BLK_END  0x400      /* Data Block End */
-#define              nDAT_BLK_END  0x0       
 #define                   CMD_ACT  0x800      /* CMD Active */
-#define                  nCMD_ACT  0x0       
 #define                    TX_ACT  0x1000     /* Transmit Active */
-#define                   nTX_ACT  0x0       
 #define                    RX_ACT  0x2000     /* Receive Active */
-#define                   nRX_ACT  0x0       
 #define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
-#define             nTX_FIFO_STAT  0x0       
 #define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
-#define             nRX_FIFO_STAT  0x0       
 #define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
-#define             nTX_FIFO_FULL  0x0       
 #define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
-#define             nRX_FIFO_FULL  0x0       
 #define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
-#define             nTX_FIFO_ZERO  0x0       
 #define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
-#define              nRX_DAT_ZERO  0x0       
 #define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
-#define               nTX_DAT_RDY  0x0       
 #define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
-#define              nRX_FIFO_RDY  0x0       
 
 /* Bit masks for SDH_STATUS_CLR */
 
 #define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
-#define        nCMD_CRC_FAIL_STAT  0x0       
 #define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
-#define        nDAT_CRC_FAIL_STAT  0x0       
 #define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
-#define         nCMD_TIMEOUT_STAT  0x0       
 #define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
-#define         nDAT_TIMEOUT_STAT  0x0       
 #define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
-#define         nTX_UNDERRUN_STAT  0x0       
 #define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
-#define          nRX_OVERRUN_STAT  0x0       
 #define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
-#define        nCMD_RESP_END_STAT  0x0       
 #define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
-#define            nCMD_SENT_STAT  0x0       
 #define              DAT_END_STAT  0x100      /* Data End Status */
-#define             nDAT_END_STAT  0x0       
 #define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
-#define       nSTART_BIT_ERR_STAT  0x0       
 #define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
-#define         nDAT_BLK_END_STAT  0x0       
 
 /* Bit masks for SDH_MASK0 */
 
 #define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
-#define        nCMD_CRC_FAIL_MASK  0x0       
 #define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
-#define        nDAT_CRC_FAIL_MASK  0x0       
 #define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
-#define         nCMD_TIMEOUT_MASK  0x0       
 #define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
-#define         nDAT_TIMEOUT_MASK  0x0       
 #define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
-#define         nTX_UNDERRUN_MASK  0x0       
 #define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
-#define          nRX_OVERRUN_MASK  0x0       
 #define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
-#define        nCMD_RESP_END_MASK  0x0       
 #define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
-#define            nCMD_SENT_MASK  0x0       
 #define              DAT_END_MASK  0x100      /* Data End Mask */
-#define             nDAT_END_MASK  0x0       
 #define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
-#define       nSTART_BIT_ERR_MASK  0x0       
 #define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
-#define         nDAT_BLK_END_MASK  0x0       
 #define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
-#define             nCMD_ACT_MASK  0x0       
 #define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
-#define              nTX_ACT_MASK  0x0       
 #define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
-#define              nRX_ACT_MASK  0x0       
 #define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
-#define        nTX_FIFO_STAT_MASK  0x0       
 #define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
-#define        nRX_FIFO_STAT_MASK  0x0       
 #define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
-#define        nTX_FIFO_FULL_MASK  0x0       
 #define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
-#define        nRX_FIFO_FULL_MASK  0x0       
 #define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
-#define        nTX_FIFO_ZERO_MASK  0x0       
 #define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
-#define         nRX_DAT_ZERO_MASK  0x0       
 #define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
-#define          nTX_DAT_RDY_MASK  0x0       
 #define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
-#define         nRX_FIFO_RDY_MASK  0x0       
 
 /* Bit masks for SDH_FIFO_CNT */
 
 /* Bit masks for SDH_E_STATUS */
 
 #define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
-#define             nSDIO_INT_DET  0x0       
 #define               SD_CARD_DET  0x10       /* SD Card Detect */
-#define              nSD_CARD_DET  0x0       
 
 /* Bit masks for SDH_E_MASK */
 
 #define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
-#define                 nSDIO_MSK  0x0       
 #define                   SCD_MSK  0x40       /* Mask Card Detect */
-#define                  nSCD_MSK  0x0       
 
 /* Bit masks for SDH_CFG */
 
 #define                   CLKS_EN  0x1        /* Clocks Enable */
-#define                  nCLKS_EN  0x0       
 #define                      SD4E  0x4        /* SDIO 4-Bit Enable */
-#define                     nSD4E  0x0       
 #define                       MWE  0x8        /* Moving Window Enable */
-#define                      nMWE  0x0       
 #define                    SD_RST  0x10       /* SDMMC Reset */
-#define                   nSD_RST  0x0       
 #define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
-#define                nPUP_SDDAT  0x0       
 #define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
-#define               nPUP_SDDAT3  0x0       
 #define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
-#define                nPD_SDDAT3  0x0       
 
 /* Bit masks for SDH_RD_WAIT_EN */
 
 #define                       RWR  0x1        /* Read Wait Request */
-#define                      nRWR  0x0       
 
 /* Bit masks for ATAPI_CONTROL */
 
 #define                 PIO_START  0x1        /* Start PIO/Reg Op */
-#define                nPIO_START  0x0       
 #define               MULTI_START  0x2        /* Start Multi-DMA Op */
-#define              nMULTI_START  0x0       
 #define               ULTRA_START  0x4        /* Start Ultra-DMA Op */
-#define              nULTRA_START  0x0       
 #define                  XFER_DIR  0x8        /* Transfer Direction */
-#define                 nXFER_DIR  0x0       
 #define                  IORDY_EN  0x10       /* IORDY Enable */
-#define                 nIORDY_EN  0x0       
 #define                FIFO_FLUSH  0x20       /* Flush FIFOs */
-#define               nFIFO_FLUSH  0x0       
 #define                  SOFT_RST  0x40       /* Soft Reset */
-#define                 nSOFT_RST  0x0       
 #define                   DEV_RST  0x80       /* Device Reset */
-#define                  nDEV_RST  0x0       
 #define                TFRCNT_RST  0x100      /* Trans Count Reset */
-#define               nTFRCNT_RST  0x0       
 #define               END_ON_TERM  0x200      /* End/Terminate Select */
-#define              nEND_ON_TERM  0x0       
 #define               PIO_USE_DMA  0x400      /* PIO-DMA Enable */
-#define              nPIO_USE_DMA  0x0       
 #define          UDMAIN_FIFO_THRS  0xf000     /* Ultra DMA-IN FIFO Threshold */
 
 /* Bit masks for ATAPI_STATUS */
 
 #define               PIO_XFER_ON  0x1        /* PIO transfer in progress */
-#define              nPIO_XFER_ON  0x0       
 #define             MULTI_XFER_ON  0x2        /* Multi-word DMA transfer in progress */
-#define            nMULTI_XFER_ON  0x0       
 #define             ULTRA_XFER_ON  0x4        /* Ultra DMA transfer in progress */
-#define            nULTRA_XFER_ON  0x0       
 #define               ULTRA_IN_FL  0xf0       /* Ultra DMA Input FIFO Level */
 
 /* Bit masks for ATAPI_DEV_ADDR */
 /* Bit masks for ATAPI_INT_MASK */
 
 #define        ATAPI_DEV_INT_MASK  0x1        /* Device interrupt mask */
-#define       nATAPI_DEV_INT_MASK  0x0       
 #define             PIO_DONE_MASK  0x2        /* PIO transfer done interrupt mask */
-#define            nPIO_DONE_MASK  0x0       
 #define           MULTI_DONE_MASK  0x4        /* Multi-DMA transfer done interrupt mask */
-#define          nMULTI_DONE_MASK  0x0       
 #define          UDMAIN_DONE_MASK  0x8        /* Ultra-DMA in transfer done interrupt mask */
-#define         nUDMAIN_DONE_MASK  0x0       
 #define         UDMAOUT_DONE_MASK  0x10       /* Ultra-DMA out transfer done interrupt mask */
-#define        nUDMAOUT_DONE_MASK  0x0       
 #define       HOST_TERM_XFER_MASK  0x20       /* Host terminate current transfer interrupt mask */
-#define      nHOST_TERM_XFER_MASK  0x0       
 #define           MULTI_TERM_MASK  0x40       /* Device terminate Multi-DMA transfer interrupt mask */
-#define          nMULTI_TERM_MASK  0x0       
 #define          UDMAIN_TERM_MASK  0x80       /* Device terminate Ultra-DMA-in transfer interrupt mask */
-#define         nUDMAIN_TERM_MASK  0x0       
 #define         UDMAOUT_TERM_MASK  0x100      /* Device terminate Ultra-DMA-out transfer interrupt mask */
-#define        nUDMAOUT_TERM_MASK  0x0       
 
 /* Bit masks for ATAPI_INT_STATUS */
 
 #define             ATAPI_DEV_INT  0x1        /* Device interrupt status */
-#define            nATAPI_DEV_INT  0x0       
 #define              PIO_DONE_INT  0x2        /* PIO transfer done interrupt status */
-#define             nPIO_DONE_INT  0x0       
 #define            MULTI_DONE_INT  0x4        /* Multi-DMA transfer done interrupt status */
-#define           nMULTI_DONE_INT  0x0       
 #define           UDMAIN_DONE_INT  0x8        /* Ultra-DMA in transfer done interrupt status */
-#define          nUDMAIN_DONE_INT  0x0       
 #define          UDMAOUT_DONE_INT  0x10       /* Ultra-DMA out transfer done interrupt status */
-#define         nUDMAOUT_DONE_INT  0x0       
 #define        HOST_TERM_XFER_INT  0x20       /* Host terminate current transfer interrupt status */
-#define       nHOST_TERM_XFER_INT  0x0       
 #define            MULTI_TERM_INT  0x40       /* Device terminate Multi-DMA transfer interrupt status */
-#define           nMULTI_TERM_INT  0x0       
 #define           UDMAIN_TERM_INT  0x80       /* Device terminate Ultra-DMA-in transfer interrupt status */
-#define          nUDMAIN_TERM_INT  0x0       
 #define          UDMAOUT_TERM_INT  0x100      /* Device terminate Ultra-DMA-out transfer interrupt status */
-#define         nUDMAOUT_TERM_INT  0x0       
 
 /* Bit masks for ATAPI_LINE_STATUS */
 
 #define                ATAPI_INTR  0x1        /* Device interrupt to host line status */
-#define               nATAPI_INTR  0x0       
 #define                ATAPI_DASP  0x2        /* Device dasp to host line status */
-#define               nATAPI_DASP  0x0       
 #define                ATAPI_CS0N  0x4        /* ATAPI chip select 0 line status */
-#define               nATAPI_CS0N  0x0       
 #define                ATAPI_CS1N  0x8        /* ATAPI chip select 1 line status */
-#define               nATAPI_CS1N  0x0       
 #define                ATAPI_ADDR  0x70       /* ATAPI address line status */
 #define              ATAPI_DMAREQ  0x80       /* ATAPI DMA request line status */
-#define             nATAPI_DMAREQ  0x0       
 #define             ATAPI_DMAACKN  0x100      /* ATAPI DMA acknowledge line status */
-#define            nATAPI_DMAACKN  0x0       
 #define               ATAPI_DIOWN  0x200      /* ATAPI write line status */
-#define              nATAPI_DIOWN  0x0       
 #define               ATAPI_DIORN  0x400      /* ATAPI read line status */
-#define              nATAPI_DIORN  0x0       
 #define               ATAPI_IORDY  0x800      /* ATAPI IORDY line status */
-#define              nATAPI_IORDY  0x0       
 
 /* Bit masks for ATAPI_SM_STATE */
 
 /* Bit masks for ATAPI_TERMINATE */
 
 #define           ATAPI_HOST_TERM  0x1        /* Host terminationation */
-#define          nATAPI_HOST_TERM  0x0       
 
 /* Bit masks for ATAPI_REG_TIM_0 */
 
 /* Bit masks for TIMER_ENABLE1 */
 
 #define                    TIMEN8  0x1        /* Timer 8 Enable */
-#define                   nTIMEN8  0x0       
 #define                    TIMEN9  0x2        /* Timer 9 Enable */
-#define                   nTIMEN9  0x0       
 #define                   TIMEN10  0x4        /* Timer 10 Enable */
-#define                  nTIMEN10  0x0       
 
 /* Bit masks for TIMER_DISABLE1 */
 
 #define                   TIMDIS8  0x1        /* Timer 8 Disable */
-#define                  nTIMDIS8  0x0       
 #define                   TIMDIS9  0x2        /* Timer 9 Disable */
-#define                  nTIMDIS9  0x0       
 #define                  TIMDIS10  0x4        /* Timer 10 Disable */
-#define                 nTIMDIS10  0x0       
 
 /* Bit masks for TIMER_STATUS1 */
 
 #define                    TIMIL8  0x1        /* Timer 8 Interrupt */
-#define                   nTIMIL8  0x0       
 #define                    TIMIL9  0x2        /* Timer 9 Interrupt */
-#define                   nTIMIL9  0x0       
 #define                   TIMIL10  0x4        /* Timer 10 Interrupt */
-#define                  nTIMIL10  0x0       
 #define                 TOVF_ERR8  0x10       /* Timer 8 Counter Overflow */
-#define                nTOVF_ERR8  0x0       
 #define                 TOVF_ERR9  0x20       /* Timer 9 Counter Overflow */
-#define                nTOVF_ERR9  0x0       
 #define                TOVF_ERR10  0x40       /* Timer 10 Counter Overflow */
-#define               nTOVF_ERR10  0x0       
 #define                     TRUN8  0x1000     /* Timer 8 Slave Enable Status */
-#define                    nTRUN8  0x0       
 #define                     TRUN9  0x2000     /* Timer 9 Slave Enable Status */
-#define                    nTRUN9  0x0       
 #define                    TRUN10  0x4000     /* Timer 10 Slave Enable Status */
-#define                   nTRUN10  0x0       
 
 /* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
 
 /* Bit masks for USB_POWER */
 
 #define           ENABLE_SUSPENDM  0x1        /* enable SuspendM output */
-#define          nENABLE_SUSPENDM  0x0       
 #define              SUSPEND_MODE  0x2        /* Suspend Mode indicator */
-#define             nSUSPEND_MODE  0x0       
 #define               RESUME_MODE  0x4        /* DMA Mode */
-#define              nRESUME_MODE  0x0       
 #define                     RESET  0x8        /* Reset indicator */
-#define                    nRESET  0x0       
 #define                   HS_MODE  0x10       /* High Speed mode indicator */
-#define                  nHS_MODE  0x0       
 #define                 HS_ENABLE  0x20       /* high Speed Enable */
-#define                nHS_ENABLE  0x0       
 #define                 SOFT_CONN  0x40       /* Soft connect */
-#define                nSOFT_CONN  0x0       
 #define                ISO_UPDATE  0x80       /* Isochronous update */
-#define               nISO_UPDATE  0x0       
 
 /* Bit masks for USB_INTRTX */
 
 #define                    EP0_TX  0x1        /* Tx Endpoint 0 interrupt */
-#define                   nEP0_TX  0x0       
 #define                    EP1_TX  0x2        /* Tx Endpoint 1 interrupt */
-#define                   nEP1_TX  0x0       
 #define                    EP2_TX  0x4        /* Tx Endpoint 2 interrupt */
-#define                   nEP2_TX  0x0       
 #define                    EP3_TX  0x8        /* Tx Endpoint 3 interrupt */
-#define                   nEP3_TX  0x0       
 #define                    EP4_TX  0x10       /* Tx Endpoint 4 interrupt */
-#define                   nEP4_TX  0x0       
 #define                    EP5_TX  0x20       /* Tx Endpoint 5 interrupt */
-#define                   nEP5_TX  0x0       
 #define                    EP6_TX  0x40       /* Tx Endpoint 6 interrupt */
-#define                   nEP6_TX  0x0       
 #define                    EP7_TX  0x80       /* Tx Endpoint 7 interrupt */
-#define                   nEP7_TX  0x0       
 
 /* Bit masks for USB_INTRRX */
 
 #define                    EP1_RX  0x2        /* Rx Endpoint 1 interrupt */
-#define                   nEP1_RX  0x0       
 #define                    EP2_RX  0x4        /* Rx Endpoint 2 interrupt */
-#define                   nEP2_RX  0x0       
 #define                    EP3_RX  0x8        /* Rx Endpoint 3 interrupt */
-#define                   nEP3_RX  0x0       
 #define                    EP4_RX  0x10       /* Rx Endpoint 4 interrupt */
-#define                   nEP4_RX  0x0       
 #define                    EP5_RX  0x20       /* Rx Endpoint 5 interrupt */
-#define                   nEP5_RX  0x0       
 #define                    EP6_RX  0x40       /* Rx Endpoint 6 interrupt */
-#define                   nEP6_RX  0x0       
 #define                    EP7_RX  0x80       /* Rx Endpoint 7 interrupt */
-#define                   nEP7_RX  0x0       
 
 /* Bit masks for USB_INTRTXE */
 
 #define                  EP0_TX_E  0x1        /* Endpoint 0 interrupt Enable */
-#define                 nEP0_TX_E  0x0       
 #define                  EP1_TX_E  0x2        /* Tx Endpoint 1 interrupt  Enable */
-#define                 nEP1_TX_E  0x0       
 #define                  EP2_TX_E  0x4        /* Tx Endpoint 2 interrupt  Enable */
-#define                 nEP2_TX_E  0x0       
 #define                  EP3_TX_E  0x8        /* Tx Endpoint 3 interrupt  Enable */
-#define                 nEP3_TX_E  0x0       
 #define                  EP4_TX_E  0x10       /* Tx Endpoint 4 interrupt  Enable */
-#define                 nEP4_TX_E  0x0       
 #define                  EP5_TX_E  0x20       /* Tx Endpoint 5 interrupt  Enable */
-#define                 nEP5_TX_E  0x0       
 #define                  EP6_TX_E  0x40       /* Tx Endpoint 6 interrupt  Enable */
-#define                 nEP6_TX_E  0x0       
 #define                  EP7_TX_E  0x80       /* Tx Endpoint 7 interrupt  Enable */
-#define                 nEP7_TX_E  0x0       
 
 /* Bit masks for USB_INTRRXE */
 
 #define                  EP1_RX_E  0x2        /* Rx Endpoint 1 interrupt  Enable */
-#define                 nEP1_RX_E  0x0       
 #define                  EP2_RX_E  0x4        /* Rx Endpoint 2 interrupt  Enable */
-#define                 nEP2_RX_E  0x0       
 #define                  EP3_RX_E  0x8        /* Rx Endpoint 3 interrupt  Enable */
-#define                 nEP3_RX_E  0x0       
 #define                  EP4_RX_E  0x10       /* Rx Endpoint 4 interrupt  Enable */
-#define                 nEP4_RX_E  0x0       
 #define                  EP5_RX_E  0x20       /* Rx Endpoint 5 interrupt  Enable */
-#define                 nEP5_RX_E  0x0       
 #define                  EP6_RX_E  0x40       /* Rx Endpoint 6 interrupt  Enable */
-#define                 nEP6_RX_E  0x0       
 #define                  EP7_RX_E  0x80       /* Rx Endpoint 7 interrupt  Enable */
-#define                 nEP7_RX_E  0x0       
 
 /* Bit masks for USB_INTRUSB */
 
 #define                 SUSPEND_B  0x1        /* Suspend indicator */
-#define                nSUSPEND_B  0x0       
 #define                  RESUME_B  0x2        /* Resume indicator */
-#define                 nRESUME_B  0x0       
 #define          RESET_OR_BABLE_B  0x4        /* Reset/babble indicator */
-#define         nRESET_OR_BABLE_B  0x0       
 #define                     SOF_B  0x8        /* Start of frame */
-#define                    nSOF_B  0x0       
 #define                    CONN_B  0x10       /* Connection indicator */
-#define                   nCONN_B  0x0       
 #define                  DISCON_B  0x20       /* Disconnect indicator */
-#define                 nDISCON_B  0x0       
 #define             SESSION_REQ_B  0x40       /* Session Request */
-#define            nSESSION_REQ_B  0x0       
 #define              VBUS_ERROR_B  0x80       /* Vbus threshold indicator */
-#define             nVBUS_ERROR_B  0x0       
 
 /* Bit masks for USB_INTRUSBE */
 
 #define                SUSPEND_BE  0x1        /* Suspend indicator int enable */
-#define               nSUSPEND_BE  0x0       
 #define                 RESUME_BE  0x2        /* Resume indicator int enable */
-#define                nRESUME_BE  0x0       
 #define         RESET_OR_BABLE_BE  0x4        /* Reset/babble indicator int enable */
-#define        nRESET_OR_BABLE_BE  0x0       
 #define                    SOF_BE  0x8        /* Start of frame int enable */
-#define                   nSOF_BE  0x0       
 #define                   CONN_BE  0x10       /* Connection indicator int enable */
-#define                  nCONN_BE  0x0       
 #define                 DISCON_BE  0x20       /* Disconnect indicator int enable */
-#define                nDISCON_BE  0x0       
 #define            SESSION_REQ_BE  0x40       /* Session Request int enable */
-#define           nSESSION_REQ_BE  0x0       
 #define             VBUS_ERROR_BE  0x80       /* Vbus threshold indicator int enable */
-#define            nVBUS_ERROR_BE  0x0       
 
 /* Bit masks for USB_FRAME */
 
 /* Bit masks for USB_GLOBAL_CTL */
 
 #define                GLOBAL_ENA  0x1        /* enables USB module */
-#define               nGLOBAL_ENA  0x0       
 #define                EP1_TX_ENA  0x2        /* Transmit endpoint 1 enable */
-#define               nEP1_TX_ENA  0x0       
 #define                EP2_TX_ENA  0x4        /* Transmit endpoint 2 enable */
-#define               nEP2_TX_ENA  0x0       
 #define                EP3_TX_ENA  0x8        /* Transmit endpoint 3 enable */
-#define               nEP3_TX_ENA  0x0       
 #define                EP4_TX_ENA  0x10       /* Transmit endpoint 4 enable */
-#define               nEP4_TX_ENA  0x0       
 #define                EP5_TX_ENA  0x20       /* Transmit endpoint 5 enable */
-#define               nEP5_TX_ENA  0x0       
 #define                EP6_TX_ENA  0x40       /* Transmit endpoint 6 enable */
-#define               nEP6_TX_ENA  0x0       
 #define                EP7_TX_ENA  0x80       /* Transmit endpoint 7 enable */
-#define               nEP7_TX_ENA  0x0       
 #define                EP1_RX_ENA  0x100      /* Receive endpoint 1 enable */
-#define               nEP1_RX_ENA  0x0       
 #define                EP2_RX_ENA  0x200      /* Receive endpoint 2 enable */
-#define               nEP2_RX_ENA  0x0       
 #define                EP3_RX_ENA  0x400      /* Receive endpoint 3 enable */
-#define               nEP3_RX_ENA  0x0       
 #define                EP4_RX_ENA  0x800      /* Receive endpoint 4 enable */
-#define               nEP4_RX_ENA  0x0       
 #define                EP5_RX_ENA  0x1000     /* Receive endpoint 5 enable */
-#define               nEP5_RX_ENA  0x0       
 #define                EP6_RX_ENA  0x2000     /* Receive endpoint 6 enable */
-#define               nEP6_RX_ENA  0x0       
 #define                EP7_RX_ENA  0x4000     /* Receive endpoint 7 enable */
-#define               nEP7_RX_ENA  0x0       
 
 /* Bit masks for USB_OTG_DEV_CTL */
 
 #define                   SESSION  0x1        /* session indicator */
-#define                  nSESSION  0x0       
 #define                  HOST_REQ  0x2        /* Host negotiation request */
-#define                 nHOST_REQ  0x0       
 #define                 HOST_MODE  0x4        /* indicates USBDRC is a host */
-#define                nHOST_MODE  0x0       
 #define                     VBUS0  0x8        /* Vbus level indicator[0] */
-#define                    nVBUS0  0x0       
 #define                     VBUS1  0x10       /* Vbus level indicator[1] */
-#define                    nVBUS1  0x0       
 #define                     LSDEV  0x20       /* Low-speed indicator */
-#define                    nLSDEV  0x0       
 #define                     FSDEV  0x40       /* Full or High-speed indicator */
-#define                    nFSDEV  0x0       
 #define                  B_DEVICE  0x80       /* A' or 'B' device indicator */
-#define                 nB_DEVICE  0x0       
 
 /* Bit masks for USB_OTG_VBUS_IRQ */
 
 #define             DRIVE_VBUS_ON  0x1        /* indicator to drive VBUS control circuit */
-#define            nDRIVE_VBUS_ON  0x0       
 #define            DRIVE_VBUS_OFF  0x2        /* indicator to shut off charge pump */
-#define           nDRIVE_VBUS_OFF  0x0       
 #define           CHRG_VBUS_START  0x4        /* indicator for external circuit to start charging VBUS */
-#define          nCHRG_VBUS_START  0x0       
 #define             CHRG_VBUS_END  0x8        /* indicator for external circuit to end charging VBUS */
-#define            nCHRG_VBUS_END  0x0       
 #define        DISCHRG_VBUS_START  0x10       /* indicator to start discharging VBUS */
-#define       nDISCHRG_VBUS_START  0x0       
 #define          DISCHRG_VBUS_END  0x20       /* indicator to stop discharging VBUS */
-#define         nDISCHRG_VBUS_END  0x0       
 
 /* Bit masks for USB_OTG_VBUS_MASK */
 
 #define         DRIVE_VBUS_ON_ENA  0x1        /* enable DRIVE_VBUS_ON interrupt */
-#define        nDRIVE_VBUS_ON_ENA  0x0       
 #define        DRIVE_VBUS_OFF_ENA  0x2        /* enable DRIVE_VBUS_OFF interrupt */
-#define       nDRIVE_VBUS_OFF_ENA  0x0       
 #define       CHRG_VBUS_START_ENA  0x4        /* enable CHRG_VBUS_START interrupt */
-#define      nCHRG_VBUS_START_ENA  0x0       
 #define         CHRG_VBUS_END_ENA  0x8        /* enable CHRG_VBUS_END interrupt */
-#define        nCHRG_VBUS_END_ENA  0x0       
 #define    DISCHRG_VBUS_START_ENA  0x10       /* enable DISCHRG_VBUS_START interrupt */
-#define   nDISCHRG_VBUS_START_ENA  0x0       
 #define      DISCHRG_VBUS_END_ENA  0x20       /* enable DISCHRG_VBUS_END interrupt */
-#define     nDISCHRG_VBUS_END_ENA  0x0       
 
 /* Bit masks for USB_CSR0 */
 
 #define                  RXPKTRDY  0x1        /* data packet receive indicator */
-#define                 nRXPKTRDY  0x0       
 #define                  TXPKTRDY  0x2        /* data packet in FIFO indicator */
-#define                 nTXPKTRDY  0x0       
 #define                STALL_SENT  0x4        /* STALL handshake sent */
-#define               nSTALL_SENT  0x0       
 #define                   DATAEND  0x8        /* Data end indicator */
-#define                  nDATAEND  0x0       
 #define                  SETUPEND  0x10       /* Setup end */
-#define                 nSETUPEND  0x0       
 #define                 SENDSTALL  0x20       /* Send STALL handshake */
-#define                nSENDSTALL  0x0       
 #define         SERVICED_RXPKTRDY  0x40       /* used to clear the RxPktRdy bit */
-#define        nSERVICED_RXPKTRDY  0x0       
 #define         SERVICED_SETUPEND  0x80       /* used to clear the SetupEnd bit */
-#define        nSERVICED_SETUPEND  0x0       
 #define                 FLUSHFIFO  0x100      /* flush endpoint FIFO */
-#define                nFLUSHFIFO  0x0       
 #define          STALL_RECEIVED_H  0x4        /* STALL handshake received host mode */
-#define         nSTALL_RECEIVED_H  0x0       
 #define                SETUPPKT_H  0x8        /* send Setup token host mode */
-#define               nSETUPPKT_H  0x0       
 #define                   ERROR_H  0x10       /* timeout error indicator host mode */
-#define                  nERROR_H  0x0       
 #define                  REQPKT_H  0x20       /* Request an IN transaction host mode */
-#define                 nREQPKT_H  0x0       
 #define               STATUSPKT_H  0x40       /* Status stage transaction host mode */
-#define              nSTATUSPKT_H  0x0       
 #define             NAK_TIMEOUT_H  0x80       /* EP0 halted after a NAK host mode */
-#define            nNAK_TIMEOUT_H  0x0       
 
 /* Bit masks for USB_COUNT0 */
 
 /* Bit masks for USB_TXCSR */
 
 #define                TXPKTRDY_T  0x1        /* data packet in FIFO indicator */
-#define               nTXPKTRDY_T  0x0       
 #define          FIFO_NOT_EMPTY_T  0x2        /* FIFO not empty */
-#define         nFIFO_NOT_EMPTY_T  0x0       
 #define                UNDERRUN_T  0x4        /* TxPktRdy not set  for an IN token */
-#define               nUNDERRUN_T  0x0       
 #define               FLUSHFIFO_T  0x8        /* flush endpoint FIFO */
-#define              nFLUSHFIFO_T  0x0       
 #define              STALL_SEND_T  0x10       /* issue a Stall handshake */
-#define             nSTALL_SEND_T  0x0       
 #define              STALL_SENT_T  0x20       /* Stall handshake transmitted */
-#define             nSTALL_SENT_T  0x0       
 #define        CLEAR_DATATOGGLE_T  0x40       /* clear endpoint data toggle */
-#define       nCLEAR_DATATOGGLE_T  0x0       
 #define                INCOMPTX_T  0x80       /* indicates that a large packet is split */
-#define               nINCOMPTX_T  0x0       
 #define              DMAREQMODE_T  0x400      /* DMA mode (0 or 1) selection */
-#define             nDMAREQMODE_T  0x0       
 #define        FORCE_DATATOGGLE_T  0x800      /* Force data toggle */
-#define       nFORCE_DATATOGGLE_T  0x0       
 #define              DMAREQ_ENA_T  0x1000     /* Enable DMA request for Tx EP */
-#define             nDMAREQ_ENA_T  0x0       
 #define                     ISO_T  0x4000     /* enable Isochronous transfers */
-#define                    nISO_T  0x0       
 #define                 AUTOSET_T  0x8000     /* allows TxPktRdy to be set automatically */
-#define                nAUTOSET_T  0x0       
 #define                  ERROR_TH  0x4        /* error condition host mode */
-#define                 nERROR_TH  0x0       
 #define         STALL_RECEIVED_TH  0x20       /* Stall handshake received host mode */
-#define        nSTALL_RECEIVED_TH  0x0       
 #define            NAK_TIMEOUT_TH  0x80       /* NAK timeout host mode */
-#define           nNAK_TIMEOUT_TH  0x0       
 
 /* Bit masks for USB_TXCOUNT */
 
 /* Bit masks for USB_RXCSR */
 
 #define                RXPKTRDY_R  0x1        /* data packet in FIFO indicator */
-#define               nRXPKTRDY_R  0x0       
 #define               FIFO_FULL_R  0x2        /* FIFO not empty */
-#define              nFIFO_FULL_R  0x0       
 #define                 OVERRUN_R  0x4        /* TxPktRdy not set  for an IN token */
-#define                nOVERRUN_R  0x0       
 #define               DATAERROR_R  0x8        /* Out packet cannot be loaded into Rx  FIFO */
-#define              nDATAERROR_R  0x0       
 #define               FLUSHFIFO_R  0x10       /* flush endpoint FIFO */
-#define              nFLUSHFIFO_R  0x0       
 #define              STALL_SEND_R  0x20       /* issue a Stall handshake */
-#define             nSTALL_SEND_R  0x0       
 #define              STALL_SENT_R  0x40       /* Stall handshake transmitted */
-#define             nSTALL_SENT_R  0x0       
 #define        CLEAR_DATATOGGLE_R  0x80       /* clear endpoint data toggle */
-#define       nCLEAR_DATATOGGLE_R  0x0       
 #define                INCOMPRX_R  0x100      /* indicates that a large packet is split */
-#define               nINCOMPRX_R  0x0       
 #define              DMAREQMODE_R  0x800      /* DMA mode (0 or 1) selection */
-#define             nDMAREQMODE_R  0x0       
 #define                 DISNYET_R  0x1000     /* disable Nyet handshakes */
-#define                nDISNYET_R  0x0       
 #define              DMAREQ_ENA_R  0x2000     /* Enable DMA request for Tx EP */
-#define             nDMAREQ_ENA_R  0x0       
 #define                     ISO_R  0x4000     /* enable Isochronous transfers */
-#define                    nISO_R  0x0       
 #define               AUTOCLEAR_R  0x8000     /* allows TxPktRdy to be set automatically */
-#define              nAUTOCLEAR_R  0x0       
 #define                  ERROR_RH  0x4        /* TxPktRdy not set  for an IN token host mode */
-#define                 nERROR_RH  0x0       
 #define                 REQPKT_RH  0x20       /* request an IN transaction host mode */
-#define                nREQPKT_RH  0x0       
 #define         STALL_RECEIVED_RH  0x40       /* Stall handshake received host mode */
-#define        nSTALL_RECEIVED_RH  0x0       
 #define               INCOMPRX_RH  0x100      /* indicates that a large packet is split host mode */
-#define              nINCOMPRX_RH  0x0       
 #define             DMAREQMODE_RH  0x800      /* DMA mode (0 or 1) selection host mode */
-#define            nDMAREQMODE_RH  0x0       
 #define                AUTOREQ_RH  0x4000     /* sets ReqPkt automatically host mode */
-#define               nAUTOREQ_RH  0x0       
 
 /* Bit masks for USB_RXCOUNT */
 
 /* Bit masks for USB_DMA_INTERRUPT */
 
 #define                  DMA0_INT  0x1        /* DMA0 pending interrupt */
-#define                 nDMA0_INT  0x0       
 #define                  DMA1_INT  0x2        /* DMA1 pending interrupt */
-#define                 nDMA1_INT  0x0       
 #define                  DMA2_INT  0x4        /* DMA2 pending interrupt */
-#define                 nDMA2_INT  0x0       
 #define                  DMA3_INT  0x8        /* DMA3 pending interrupt */
-#define                 nDMA3_INT  0x0       
 #define                  DMA4_INT  0x10       /* DMA4 pending interrupt */
-#define                 nDMA4_INT  0x0       
 #define                  DMA5_INT  0x20       /* DMA5 pending interrupt */
-#define                 nDMA5_INT  0x0       
 #define                  DMA6_INT  0x40       /* DMA6 pending interrupt */
-#define                 nDMA6_INT  0x0       
 #define                  DMA7_INT  0x80       /* DMA7 pending interrupt */
-#define                 nDMA7_INT  0x0       
 
 /* Bit masks for USB_DMAxCONTROL */
 
 #define                   DMA_ENA  0x1        /* DMA enable */
-#define                  nDMA_ENA  0x0       
 #define                 DIRECTION  0x2        /* direction of DMA transfer */
-#define                nDIRECTION  0x0       
 #define                      MODE  0x4        /* DMA Bus error */
-#define                     nMODE  0x0       
 #define                   INT_ENA  0x8        /* Interrupt enable */
-#define                  nINT_ENA  0x0       
 #define                     EPNUM  0xf0       /* EP number */
 #define                  BUSERROR  0x100      /* DMA Bus error */
-#define                 nBUSERROR  0x0       
 
 /* Bit masks for USB_DMAxADDRHIGH */
 
 /* Bit masks for HMDMAx_CONTROL */
 
 #define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
-#define                  nHMDMAEN  0x0       
 #define                       REP  0x2        /* Handshake MDMA Request Polarity */
-#define                      nREP  0x0       
 #define                       UTE  0x8        /* Urgency Threshold Enable */
-#define                      nUTE  0x0       
 #define                       OIE  0x10       /* Overflow Interrupt Enable */
-#define                      nOIE  0x0       
 #define                      BDIE  0x20       /* Block Done Interrupt Enable */
-#define                     nBDIE  0x0       
 #define                      MBDI  0x40       /* Mask Block Done Interrupt */
-#define                     nMBDI  0x0       
 #define                       DRQ  0x300      /* Handshake MDMA Request Type */
 #define                       RBC  0x1000     /* Force Reload of BCOUNT */
-#define                      nRBC  0x0       
 #define                        PS  0x2000     /* Pin Status */
-#define                       nPS  0x0       
 #define                        OI  0x4000     /* Overflow Interrupt Generated */
-#define                       nOI  0x0       
 #define                       BDI  0x8000     /* Block Done Interrupt Generated */
-#define                      nBDI  0x0       
 
 /* ******************************************* */
 /*     MULTI BIT MACRO ENUMERATIONS            */
index b1cc1c073b4115f5cf41b160beabcfe6bf517991..c2f4734da48df9ca9d96a02d868c2af734e6a9a9 100644 (file)
 /* Bit masks for PIXC_CTL */
 
 #define                   PIXC_EN  0x1        /* Pixel Compositor Enable */
-#define                  nPIXC_EN  0x0       
 #define                  OVR_A_EN  0x2        /* Overlay A Enable */
-#define                 nOVR_A_EN  0x0       
 #define                  OVR_B_EN  0x4        /* Overlay B Enable */
-#define                 nOVR_B_EN  0x0       
 #define                  IMG_FORM  0x8        /* Image Data Format */
-#define                 nIMG_FORM  0x0       
 #define                  OVR_FORM  0x10       /* Overlay Data Format */
-#define                 nOVR_FORM  0x0       
 #define                  OUT_FORM  0x20       /* Output Data Format */
-#define                 nOUT_FORM  0x0       
 #define                   UDS_MOD  0x40       /* Resampling Mode */
-#define                  nUDS_MOD  0x0       
 #define                     TC_EN  0x80       /* Transparent Color Enable */
-#define                    nTC_EN  0x0       
 #define                  IMG_STAT  0x300      /* Image FIFO Status */
 #define                  OVR_STAT  0xc00      /* Overlay FIFO Status */
 #define                    WM_LVL  0x3000     /* FIFO Watermark Level */
 /* Bit masks for PIXC_INTRSTAT */
 
 #define                OVR_INT_EN  0x1        /* Interrupt at End of Last Valid Overlay */
-#define               nOVR_INT_EN  0x0       
 #define                FRM_INT_EN  0x2        /* Interrupt at End of Frame */
-#define               nFRM_INT_EN  0x0       
 #define              OVR_INT_STAT  0x4        /* Overlay Interrupt Status */
-#define             nOVR_INT_STAT  0x0       
 #define              FRM_INT_STAT  0x8        /* Frame Interrupt Status */
-#define             nFRM_INT_STAT  0x0       
 
 /* Bit masks for PIXC_RYCON */
 
 #define                       A12  0xffc00    /* A12 in the Coefficient Matrix */
 #define                       A13  0x3ff00000 /* A13 in the Coefficient Matrix */
 #define                  RY_MULT4  0x40000000 /* Multiply Row by 4 */
-#define                 nRY_MULT4  0x0       
 
 /* Bit masks for PIXC_GUCON */
 
 #define                       A22  0xffc00    /* A22 in the Coefficient Matrix */
 #define                       A23  0x3ff00000 /* A23 in the Coefficient Matrix */
 #define                  GU_MULT4  0x40000000 /* Multiply Row by 4 */
-#define                 nGU_MULT4  0x0       
 
 /* Bit masks for PIXC_BVCON */
 
 #define                       A32  0xffc00    /* A32 in the Coefficient Matrix */
 #define                       A33  0x3ff00000 /* A33 in the Coefficient Matrix */
 #define                  BV_MULT4  0x40000000 /* Multiply Row by 4 */
-#define                 nBV_MULT4  0x0       
 
 /* Bit masks for PIXC_CCBIAS */
 
 /* Bit masks for HOST_CONTROL */
 
 #define                   HOST_EN  0x1        /* Host Enable */
-#define                  nHOST_EN  0x0       
 #define                  HOST_END  0x2        /* Host Endianess */
-#define                 nHOST_END  0x0       
 #define                 DATA_SIZE  0x4        /* Data Size */
-#define                nDATA_SIZE  0x0       
 #define                  HOST_RST  0x8        /* Host Reset */
-#define                 nHOST_RST  0x0       
 #define                  HRDY_OVR  0x20       /* Host Ready Override */
-#define                 nHRDY_OVR  0x0       
 #define                  INT_MODE  0x40       /* Interrupt Mode */
-#define                 nINT_MODE  0x0       
 #define                     BT_EN  0x80       /* Bus Timeout Enable */
-#define                    nBT_EN  0x0       
 #define                       EHW  0x100      /* Enable Host Write */
-#define                      nEHW  0x0       
 #define                       EHR  0x200      /* Enable Host Read */
-#define                      nEHR  0x0       
 #define                       BDR  0x400      /* Burst DMA Requests */
-#define                      nBDR  0x0       
 
 /* Bit masks for HOST_STATUS */
 
 #define                     READY  0x1        /* DMA Ready */
-#define                    nREADY  0x0       
 #define                  FIFOFULL  0x2        /* FIFO Full */
-#define                 nFIFOFULL  0x0       
 #define                 FIFOEMPTY  0x4        /* FIFO Empty */
-#define                nFIFOEMPTY  0x0       
-#define                  COMPLETE  0x8        /* DMA Complete */
-#define                 nCOMPLETE  0x0       
+#define              DMA_COMPLETE  0x8        /* DMA Complete */
 #define                      HSHK  0x10       /* Host Handshake */
-#define                     nHSHK  0x0       
 #define                   TIMEOUT  0x20       /* Host Timeout */
-#define                  nTIMEOUT  0x0       
 #define                      HIRQ  0x40       /* Host Interrupt Request */
-#define                     nHIRQ  0x0       
 #define                ALLOW_CNFG  0x80       /* Allow New Configuration */
-#define               nALLOW_CNFG  0x0       
 #define                   DMA_DIR  0x100      /* DMA Direction */
-#define                  nDMA_DIR  0x0       
 #define                       BTE  0x200      /* Bus Timeout Enabled */
-#define                      nBTE  0x0       
 
 /* Bit masks for HOST_TIMEOUT */
 
 /* Bit masks for MXVR_CONFIG */
 
 #define                    MXVREN  0x1        /* MXVR Enable */
-#define                   nMXVREN  0x0       
 #define                      MMSM  0x2        /* MXVR Master/Slave Mode Select */
-#define                     nMMSM  0x0       
 #define                    ACTIVE  0x4        /* Active Mode */
-#define                   nACTIVE  0x0       
 #define                    SDELAY  0x8        /* Synchronous Data Delay */
-#define                   nSDELAY  0x0       
 #define                   NCMRXEN  0x10       /* Normal Control Message Receive Enable */
-#define                  nNCMRXEN  0x0       
 #define                   RWRRXEN  0x20       /* Remote Write Receive Enable */
-#define                  nRWRRXEN  0x0       
 #define                     MTXEN  0x40       /* MXVR Transmit Data Enable */
-#define                    nMTXEN  0x0       
 #define                    MTXONB  0x80       /* MXVR Phy Transmitter On */
-#define                   nMTXONB  0x0       
 #define                   EPARITY  0x100      /* Even Parity Select */
-#define                  nEPARITY  0x0       
 #define                       MSB  0x1e00     /* Master Synchronous Boundary */
 #define                    APRXEN  0x2000     /* Asynchronous Packet Receive Enable */
-#define                   nAPRXEN  0x0       
 #define                    WAKEUP  0x4000     /* Wake-Up */
-#define                   nWAKEUP  0x0       
 #define                     LMECH  0x8000     /* Lock Mechanism Select */
-#define                    nLMECH  0x0       
 
 /* Bit masks for MXVR_STATE_0 */
 
 #define                      NACT  0x1        /* Network Activity */
-#define                     nNACT  0x0       
 #define                    SBLOCK  0x2        /* Super Block Lock */
-#define                   nSBLOCK  0x0       
 #define                   FMPLLST  0xc        /* Frequency Multiply PLL SM State */
 #define                  CDRPLLST  0xe0       /* Clock/Data Recovery PLL SM State */
 #define                     APBSY  0x100      /* Asynchronous Packet Transmit Buffer Busy */
-#define                    nAPBSY  0x0       
 #define                     APARB  0x200      /* Asynchronous Packet Arbitrating */
-#define                    nAPARB  0x0       
 #define                      APTX  0x400      /* Asynchronous Packet Transmitting */
-#define                     nAPTX  0x0       
 #define                      APRX  0x800      /* Receiving Asynchronous Packet */
-#define                     nAPRX  0x0       
 #define                     CMBSY  0x1000     /* Control Message Transmit Buffer Busy */
-#define                    nCMBSY  0x0       
 #define                     CMARB  0x2000     /* Control Message Arbitrating */
-#define                    nCMARB  0x0       
 #define                      CMTX  0x4000     /* Control Message Transmitting */
-#define                     nCMTX  0x0       
 #define                      CMRX  0x8000     /* Receiving Control Message */
-#define                     nCMRX  0x0       
 #define                    MRXONB  0x10000    /* MRXONB Pin State */
-#define                   nMRXONB  0x0       
 #define                     RGSIP  0x20000    /* Remote Get Source In Progress */
-#define                    nRGSIP  0x0       
 #define                     DALIP  0x40000    /* Resource Deallocate In Progress */
-#define                    nDALIP  0x0       
 #define                      ALIP  0x80000    /* Resource Allocate In Progress */
-#define                     nALIP  0x0       
 #define                     RRDIP  0x100000   /* Remote Read In Progress */
-#define                    nRRDIP  0x0       
 #define                     RWRIP  0x200000   /* Remote Write In Progress */
-#define                    nRWRIP  0x0       
 #define                     FLOCK  0x400000   /* Frame Lock */
-#define                    nFLOCK  0x0       
 #define                     BLOCK  0x800000   /* Block Lock */
-#define                    nBLOCK  0x0       
 #define                       RSB  0xf000000  /* Received Synchronous Boundary */
 #define                   DERRNUM  0xf0000000 /* DMA Error Channel Number */
 
 #define                   SRXNUMB  0xf        /* Synchronous Receive FIFO Number of Bytes */
 #define                   STXNUMB  0xf0       /* Synchronous Transmit FIFO Number of Bytes */
 #define                    APCONT  0x100      /* Asynchronous Packet Continuation */
-#define                   nAPCONT  0x0       
 #define                  OBERRNUM  0xe00      /* DMA Out of Bounds Error Channel Number */
 #define                DMAACTIVE0  0x10000    /* DMA0 Active */
-#define               nDMAACTIVE0  0x0       
 #define                DMAACTIVE1  0x20000    /* DMA1 Active */
-#define               nDMAACTIVE1  0x0       
 #define                DMAACTIVE2  0x40000    /* DMA2 Active */
-#define               nDMAACTIVE2  0x0       
 #define                DMAACTIVE3  0x80000    /* DMA3 Active */
-#define               nDMAACTIVE3  0x0       
 #define                DMAACTIVE4  0x100000   /* DMA4 Active */
-#define               nDMAACTIVE4  0x0       
 #define                DMAACTIVE5  0x200000   /* DMA5 Active */
-#define               nDMAACTIVE5  0x0       
 #define                DMAACTIVE6  0x400000   /* DMA6 Active */
-#define               nDMAACTIVE6  0x0       
 #define                DMAACTIVE7  0x800000   /* DMA7 Active */
-#define               nDMAACTIVE7  0x0       
 #define                  DMAPMEN0  0x1000000  /* DMA0 Pattern Matching Enabled */
-#define                 nDMAPMEN0  0x0       
 #define                  DMAPMEN1  0x2000000  /* DMA1 Pattern Matching Enabled */
-#define                 nDMAPMEN1  0x0       
 #define                  DMAPMEN2  0x4000000  /* DMA2 Pattern Matching Enabled */
-#define                 nDMAPMEN2  0x0       
 #define                  DMAPMEN3  0x8000000  /* DMA3 Pattern Matching Enabled */
-#define                 nDMAPMEN3  0x0       
 #define                  DMAPMEN4  0x10000000 /* DMA4 Pattern Matching Enabled */
-#define                 nDMAPMEN4  0x0       
 #define                  DMAPMEN5  0x20000000 /* DMA5 Pattern Matching Enabled */
-#define                 nDMAPMEN5  0x0       
 #define                  DMAPMEN6  0x40000000 /* DMA6 Pattern Matching Enabled */
-#define                 nDMAPMEN6  0x0       
 #define                  DMAPMEN7  0x80000000 /* DMA7 Pattern Matching Enabled */
-#define                 nDMAPMEN7  0x0       
 
 /* Bit masks for MXVR_INT_STAT_0 */
 
 #define                      NI2A  0x1        /* Network Inactive to Active */
-#define                     nNI2A  0x0       
 #define                      NA2I  0x2        /* Network Active to Inactive */
-#define                     nNA2I  0x0       
 #define                     SBU2L  0x4        /* Super Block Unlock to Lock */
-#define                    nSBU2L  0x0       
 #define                     SBL2U  0x8        /* Super Block Lock to Unlock */
-#define                    nSBL2U  0x0       
 #define                       PRU  0x10       /* Position Register Updated */
-#define                      nPRU  0x0       
 #define                      MPRU  0x20       /* Maximum Position Register Updated */
-#define                     nMPRU  0x0       
 #define                       DRU  0x40       /* Delay Register Updated */
-#define                      nDRU  0x0       
 #define                      MDRU  0x80       /* Maximum Delay Register Updated */
-#define                     nMDRU  0x0       
 #define                       SBU  0x100      /* Synchronous Boundary Updated */
-#define                      nSBU  0x0       
 #define                       ATU  0x200      /* Allocation Table Updated */
-#define                      nATU  0x0       
 #define                      FCZ0  0x400      /* Frame Counter 0 Zero */
-#define                     nFCZ0  0x0       
 #define                      FCZ1  0x800      /* Frame Counter 1 Zero */
-#define                     nFCZ1  0x0       
 #define                      PERR  0x1000     /* Parity Error */
-#define                     nPERR  0x0       
 #define                      MH2L  0x2000     /* MRXONB High to Low */
-#define                     nMH2L  0x0       
 #define                      ML2H  0x4000     /* MRXONB Low to High */
-#define                     nML2H  0x0       
 #define                       WUP  0x8000     /* Wake-Up Preamble Received */
-#define                      nWUP  0x0       
 #define                      FU2L  0x10000    /* Frame Unlock to Lock */
-#define                     nFU2L  0x0       
 #define                      FL2U  0x20000    /* Frame Lock to Unlock */
-#define                     nFL2U  0x0       
 #define                      BU2L  0x40000    /* Block Unlock to Lock */
-#define                     nBU2L  0x0       
 #define                      BL2U  0x80000    /* Block Lock to Unlock */
-#define                     nBL2U  0x0       
 #define                     OBERR  0x100000   /* DMA Out of Bounds Error */
-#define                    nOBERR  0x0       
 #define                       PFL  0x200000   /* PLL Frequency Locked */
-#define                      nPFL  0x0       
 #define                       SCZ  0x400000   /* System Clock Counter Zero */
-#define                      nSCZ  0x0       
 #define                      FERR  0x800000   /* FIFO Error */
-#define                     nFERR  0x0       
 #define                       CMR  0x1000000  /* Control Message Received */
-#define                      nCMR  0x0       
 #define                     CMROF  0x2000000  /* Control Message Receive Buffer Overflow */
-#define                    nCMROF  0x0       
 #define                      CMTS  0x4000000  /* Control Message Transmit Buffer Successfully Sent */
-#define                     nCMTS  0x0       
 #define                      CMTC  0x8000000  /* Control Message Transmit Buffer Successfully Cancelled */
-#define                     nCMTC  0x0       
 #define                      RWRC  0x10000000 /* Remote Write Control Message Completed */
-#define                     nRWRC  0x0       
 #define                       BCZ  0x20000000 /* Block Counter Zero */
-#define                      nBCZ  0x0       
 #define                     BMERR  0x40000000 /* Biphase Mark Coding Error */
-#define                    nBMERR  0x0       
 #define                      DERR  0x80000000 /* DMA Error */
-#define                     nDERR  0x0       
 
 /* Bit masks for MXVR_INT_STAT_1 */
 
 #define                    HDONE0  0x1        /* DMA0 Half Done */
-#define                   nHDONE0  0x0       
 #define                     DONE0  0x2        /* DMA0 Done */
-#define                    nDONE0  0x0       
 #define                       APR  0x4        /* Asynchronous Packet Received */
-#define                      nAPR  0x0       
 #define                     APROF  0x8        /* Asynchronous Packet Receive Buffer Overflow */
-#define                    nAPROF  0x0       
 #define                    HDONE1  0x10       /* DMA1 Half Done */
-#define                   nHDONE1  0x0       
 #define                     DONE1  0x20       /* DMA1 Done */
-#define                    nDONE1  0x0       
 #define                      APTS  0x40       /* Asynchronous Packet Transmit Buffer Successfully Sent */
-#define                     nAPTS  0x0       
 #define                      APTC  0x80       /* Asynchronous Packet Transmit Buffer Successfully Cancelled */
-#define                     nAPTC  0x0       
 #define                    HDONE2  0x100      /* DMA2 Half Done */
-#define                   nHDONE2  0x0       
 #define                     DONE2  0x200      /* DMA2 Done */
-#define                    nDONE2  0x0       
 #define                     APRCE  0x400      /* Asynchronous Packet Receive CRC Error */
-#define                    nAPRCE  0x0       
 #define                     APRPE  0x800      /* Asynchronous Packet Receive Packet Error */
-#define                    nAPRPE  0x0       
 #define                    HDONE3  0x1000     /* DMA3 Half Done */
-#define                   nHDONE3  0x0       
 #define                     DONE3  0x2000     /* DMA3 Done */
-#define                    nDONE3  0x0       
 #define                    HDONE4  0x10000    /* DMA4 Half Done */
-#define                   nHDONE4  0x0       
 #define                     DONE4  0x20000    /* DMA4 Done */
-#define                    nDONE4  0x0       
 #define                    HDONE5  0x100000   /* DMA5 Half Done */
-#define                   nHDONE5  0x0       
 #define                     DONE5  0x200000   /* DMA5 Done */
-#define                    nDONE5  0x0       
 #define                    HDONE6  0x1000000  /* DMA6 Half Done */
-#define                   nHDONE6  0x0       
 #define                     DONE6  0x2000000  /* DMA6 Done */
-#define                    nDONE6  0x0       
 #define                    HDONE7  0x10000000 /* DMA7 Half Done */
-#define                   nHDONE7  0x0       
 #define                     DONE7  0x20000000 /* DMA7 Done */
-#define                    nDONE7  0x0       
 
 /* Bit masks for MXVR_INT_EN_0 */
 
 #define                    NI2AEN  0x1        /* Network Inactive to Active Interrupt Enable */
-#define                   nNI2AEN  0x0       
 #define                    NA2IEN  0x2        /* Network Active to Inactive Interrupt Enable */
-#define                   nNA2IEN  0x0       
 #define                   SBU2LEN  0x4        /* Super Block Unlock to Lock Interrupt Enable */
-#define                  nSBU2LEN  0x0       
 #define                   SBL2UEN  0x8        /* Super Block Lock to Unlock Interrupt Enable */
-#define                  nSBL2UEN  0x0       
 #define                     PRUEN  0x10       /* Position Register Updated Interrupt Enable */
-#define                    nPRUEN  0x0       
 #define                    MPRUEN  0x20       /* Maximum Position Register Updated Interrupt Enable */
-#define                   nMPRUEN  0x0       
 #define                     DRUEN  0x40       /* Delay Register Updated Interrupt Enable */
-#define                    nDRUEN  0x0       
 #define                    MDRUEN  0x80       /* Maximum Delay Register Updated Interrupt Enable */
-#define                   nMDRUEN  0x0       
 #define                     SBUEN  0x100      /* Synchronous Boundary Updated Interrupt Enable */
-#define                    nSBUEN  0x0       
 #define                     ATUEN  0x200      /* Allocation Table Updated Interrupt Enable */
-#define                    nATUEN  0x0       
 #define                    FCZ0EN  0x400      /* Frame Counter 0 Zero Interrupt Enable */
-#define                   nFCZ0EN  0x0       
 #define                    FCZ1EN  0x800      /* Frame Counter 1 Zero Interrupt Enable */
-#define                   nFCZ1EN  0x0       
 #define                    PERREN  0x1000     /* Parity Error Interrupt Enable */
-#define                   nPERREN  0x0       
 #define                    MH2LEN  0x2000     /* MRXONB High to Low Interrupt Enable */
-#define                   nMH2LEN  0x0       
 #define                    ML2HEN  0x4000     /* MRXONB Low to High Interrupt Enable */
-#define                   nML2HEN  0x0       
 #define                     WUPEN  0x8000     /* Wake-Up Preamble Received Interrupt Enable */
-#define                    nWUPEN  0x0       
 #define                    FU2LEN  0x10000    /* Frame Unlock to Lock Interrupt Enable */
-#define                   nFU2LEN  0x0       
 #define                    FL2UEN  0x20000    /* Frame Lock to Unlock Interrupt Enable */
-#define                   nFL2UEN  0x0       
 #define                    BU2LEN  0x40000    /* Block Unlock to Lock Interrupt Enable */
-#define                   nBU2LEN  0x0       
 #define                    BL2UEN  0x80000    /* Block Lock to Unlock Interrupt Enable */
-#define                   nBL2UEN  0x0       
 #define                   OBERREN  0x100000   /* DMA Out of Bounds Error Interrupt Enable */
-#define                  nOBERREN  0x0       
 #define                     PFLEN  0x200000   /* PLL Frequency Locked Interrupt Enable */
-#define                    nPFLEN  0x0       
 #define                     SCZEN  0x400000   /* System Clock Counter Zero Interrupt Enable */
-#define                    nSCZEN  0x0       
 #define                    FERREN  0x800000   /* FIFO Error Interrupt Enable */
-#define                   nFERREN  0x0       
 #define                     CMREN  0x1000000  /* Control Message Received Interrupt Enable */
-#define                    nCMREN  0x0       
 #define                   CMROFEN  0x2000000  /* Control Message Receive Buffer Overflow Interrupt Enable */
-#define                  nCMROFEN  0x0       
 #define                    CMTSEN  0x4000000  /* Control Message Transmit Buffer Successfully Sent Interrupt Enable */
-#define                   nCMTSEN  0x0       
 #define                    CMTCEN  0x8000000  /* Control Message Transmit Buffer Successfully Cancelled Interrupt Enable */
-#define                   nCMTCEN  0x0       
 #define                    RWRCEN  0x10000000 /* Remote Write Control Message Completed Interrupt Enable */
-#define                   nRWRCEN  0x0       
 #define                     BCZEN  0x20000000 /* Block Counter Zero Interrupt Enable */
-#define                    nBCZEN  0x0       
 #define                   BMERREN  0x40000000 /* Biphase Mark Coding Error Interrupt Enable */
-#define                  nBMERREN  0x0       
 #define                    DERREN  0x80000000 /* DMA Error Interrupt Enable */
-#define                   nDERREN  0x0       
 
 /* Bit masks for MXVR_INT_EN_1 */
 
 #define                  HDONEEN0  0x1        /* DMA0 Half Done Interrupt Enable */
-#define                 nHDONEEN0  0x0       
 #define                   DONEEN0  0x2        /* DMA0 Done Interrupt Enable */
-#define                  nDONEEN0  0x0       
 #define                     APREN  0x4        /* Asynchronous Packet Received Interrupt Enable */
-#define                    nAPREN  0x0       
 #define                   APROFEN  0x8        /* Asynchronous Packet Receive Buffer Overflow Interrupt Enable */
-#define                  nAPROFEN  0x0       
 #define                  HDONEEN1  0x10       /* DMA1 Half Done Interrupt Enable */
-#define                 nHDONEEN1  0x0       
 #define                   DONEEN1  0x20       /* DMA1 Done Interrupt Enable */
-#define                  nDONEEN1  0x0       
 #define                    APTSEN  0x40       /* Asynchronous Packet Transmit Buffer Successfully Sent Interrupt Enable */
-#define                   nAPTSEN  0x0       
 #define                    APTCEN  0x80       /* Asynchronous Packet Transmit Buffer Successfully Cancelled Interrupt Enable */
-#define                   nAPTCEN  0x0       
 #define                  HDONEEN2  0x100      /* DMA2 Half Done Interrupt Enable */
-#define                 nHDONEEN2  0x0       
 #define                   DONEEN2  0x200      /* DMA2 Done Interrupt Enable */
-#define                  nDONEEN2  0x0       
 #define                   APRCEEN  0x400      /* Asynchronous Packet Receive CRC Error Interrupt Enable */
-#define                  nAPRCEEN  0x0       
 #define                   APRPEEN  0x800      /* Asynchronous Packet Receive Packet Error Interrupt Enable */
-#define                  nAPRPEEN  0x0       
 #define                  HDONEEN3  0x1000     /* DMA3 Half Done Interrupt Enable */
-#define                 nHDONEEN3  0x0       
 #define                   DONEEN3  0x2000     /* DMA3 Done Interrupt Enable */
-#define                  nDONEEN3  0x0       
 #define                  HDONEEN4  0x10000    /* DMA4 Half Done Interrupt Enable */
-#define                 nHDONEEN4  0x0       
 #define                   DONEEN4  0x20000    /* DMA4 Done Interrupt Enable */
-#define                  nDONEEN4  0x0       
 #define                  HDONEEN5  0x100000   /* DMA5 Half Done Interrupt Enable */
-#define                 nHDONEEN5  0x0       
 #define                   DONEEN5  0x200000   /* DMA5 Done Interrupt Enable */
-#define                  nDONEEN5  0x0       
 #define                  HDONEEN6  0x1000000  /* DMA6 Half Done Interrupt Enable */
-#define                 nHDONEEN6  0x0       
 #define                   DONEEN6  0x2000000  /* DMA6 Done Interrupt Enable */
-#define                  nDONEEN6  0x0       
 #define                  HDONEEN7  0x10000000 /* DMA7 Half Done Interrupt Enable */
-#define                 nHDONEEN7  0x0       
 #define                   DONEEN7  0x20000000 /* DMA7 Done Interrupt Enable */
-#define                  nDONEEN7  0x0       
 
 /* Bit masks for MXVR_POSITION */
 
 #define                  POSITION  0x3f       /* Node Position */
 #define                    PVALID  0x8000     /* Node Position Valid */
-#define                   nPVALID  0x0       
 
 /* Bit masks for MXVR_MAX_POSITION */
 
 #define                 MPOSITION  0x3f       /* Maximum Node Position */
 #define                   MPVALID  0x8000     /* Maximum Node Position Valid */
-#define                  nMPVALID  0x0       
 
 /* Bit masks for MXVR_DELAY */
 
 #define                     DELAY  0x3f       /* Node Frame Delay */
 #define                    DVALID  0x8000     /* Node Frame Delay Valid */
-#define                   nDVALID  0x0       
 
 /* Bit masks for MXVR_MAX_DELAY */
 
 #define                    MDELAY  0x3f       /* Maximum Node Frame Delay */
 #define                   MDVALID  0x8000     /* Maximum Node Frame Delay Valid */
-#define                  nMDVALID  0x0       
 
 /* Bit masks for MXVR_LADDR */
 
 #define                     LADDR  0xffff     /* Logical Address */
 #define                    LVALID  0x80000000 /* Logical Address Valid */
-#define                   nLVALID  0x0       
 
 /* Bit masks for MXVR_GADDR */
 
 #define                    GADDRL  0xff       /* Group Address Lower Byte */
 #define                    GVALID  0x8000     /* Group Address Valid */
-#define                   nGVALID  0x0       
 
 /* Bit masks for MXVR_AADDR */
 
 #define                     AADDR  0xffff     /* Alternate Address */
 #define                    AVALID  0x80000000 /* Alternate Address Valid */
-#define                   nAVALID  0x0       
 
 /* Bit masks for MXVR_ALLOC_0 */
 
 #define                       CL0  0x7f       /* Channel 0 Connection Label */
 #define                      CIU0  0x80       /* Channel 0 In Use */
-#define                     nCIU0  0x0       
 #define                       CL1  0x7f00     /* Channel 0 Connection Label */
 #define                      CIU1  0x8000     /* Channel 0 In Use */
-#define                     nCIU1  0x0       
 #define                       CL2  0x7f0000   /* Channel 0 Connection Label */
 #define                      CIU2  0x800000   /* Channel 0 In Use */
-#define                     nCIU2  0x0       
 #define                       CL3  0x7f000000 /* Channel 0 Connection Label */
 #define                      CIU3  0x80000000 /* Channel 0 In Use */
-#define                     nCIU3  0x0       
 
 /* Bit masks for MXVR_ALLOC_1 */
 
 #define                       CL4  0x7f       /* Channel 4 Connection Label */
 #define                      CIU4  0x80       /* Channel 4 In Use */
-#define                     nCIU4  0x0       
 #define                       CL5  0x7f00     /* Channel 5 Connection Label */
 #define                      CIU5  0x8000     /* Channel 5 In Use */
-#define                     nCIU5  0x0       
 #define                       CL6  0x7f0000   /* Channel 6 Connection Label */
 #define                      CIU6  0x800000   /* Channel 6 In Use */
-#define                     nCIU6  0x0       
 #define                       CL7  0x7f000000 /* Channel 7 Connection Label */
 #define                      CIU7  0x80000000 /* Channel 7 In Use */
-#define                     nCIU7  0x0       
 
 /* Bit masks for MXVR_ALLOC_2 */
 
 #define                       CL8  0x7f       /* Channel 8 Connection Label */
 #define                      CIU8  0x80       /* Channel 8 In Use */
-#define                     nCIU8  0x0       
 #define                       CL9  0x7f00     /* Channel 9 Connection Label */
 #define                      CIU9  0x8000     /* Channel 9 In Use */
-#define                     nCIU9  0x0       
 #define                      CL10  0x7f0000   /* Channel 10 Connection Label */
 #define                     CIU10  0x800000   /* Channel 10 In Use */
-#define                    nCIU10  0x0       
 #define                      CL11  0x7f000000 /* Channel 11 Connection Label */
 #define                     CIU11  0x80000000 /* Channel 11 In Use */
-#define                    nCIU11  0x0       
 
 /* Bit masks for MXVR_ALLOC_3 */
 
 #define                      CL12  0x7f       /* Channel 12 Connection Label */
 #define                     CIU12  0x80       /* Channel 12 In Use */
-#define                    nCIU12  0x0       
 #define                      CL13  0x7f00     /* Channel 13 Connection Label */
 #define                     CIU13  0x8000     /* Channel 13 In Use */
-#define                    nCIU13  0x0       
 #define                      CL14  0x7f0000   /* Channel 14 Connection Label */
 #define                     CIU14  0x800000   /* Channel 14 In Use */
-#define                    nCIU14  0x0       
 #define                      CL15  0x7f000000 /* Channel 15 Connection Label */
 #define                     CIU15  0x80000000 /* Channel 15 In Use */
-#define                    nCIU15  0x0       
 
 /* Bit masks for MXVR_ALLOC_4 */
 
 #define                      CL16  0x7f       /* Channel 16 Connection Label */
 #define                     CIU16  0x80       /* Channel 16 In Use */
-#define                    nCIU16  0x0       
 #define                      CL17  0x7f00     /* Channel 17 Connection Label */
 #define                     CIU17  0x8000     /* Channel 17 In Use */
-#define                    nCIU17  0x0       
 #define                      CL18  0x7f0000   /* Channel 18 Connection Label */
 #define                     CIU18  0x800000   /* Channel 18 In Use */
-#define                    nCIU18  0x0       
 #define                      CL19  0x7f000000 /* Channel 19 Connection Label */
 #define                     CIU19  0x80000000 /* Channel 19 In Use */
-#define                    nCIU19  0x0       
 
 /* Bit masks for MXVR_ALLOC_5 */
 
 #define                      CL20  0x7f       /* Channel 20 Connection Label */
 #define                     CIU20  0x80       /* Channel 20 In Use */
-#define                    nCIU20  0x0       
 #define                      CL21  0x7f00     /* Channel 21 Connection Label */
 #define                     CIU21  0x8000     /* Channel 21 In Use */
-#define                    nCIU21  0x0       
 #define                      CL22  0x7f0000   /* Channel 22 Connection Label */
 #define                     CIU22  0x800000   /* Channel 22 In Use */
-#define                    nCIU22  0x0       
 #define                      CL23  0x7f000000 /* Channel 23 Connection Label */
 #define                     CIU23  0x80000000 /* Channel 23 In Use */
-#define                    nCIU23  0x0       
 
 /* Bit masks for MXVR_ALLOC_6 */
 
 #define                      CL24  0x7f       /* Channel 24 Connection Label */
 #define                     CIU24  0x80       /* Channel 24 In Use */
-#define                    nCIU24  0x0       
 #define                      CL25  0x7f00     /* Channel 25 Connection Label */
 #define                     CIU25  0x8000     /* Channel 25 In Use */
-#define                    nCIU25  0x0       
 #define                      CL26  0x7f0000   /* Channel 26 Connection Label */
 #define                     CIU26  0x800000   /* Channel 26 In Use */
-#define                    nCIU26  0x0       
 #define                      CL27  0x7f000000 /* Channel 27 Connection Label */
 #define                     CIU27  0x80000000 /* Channel 27 In Use */
-#define                    nCIU27  0x0       
 
 /* Bit masks for MXVR_ALLOC_7 */
 
 #define                      CL28  0x7f       /* Channel 28 Connection Label */
 #define                     CIU28  0x80       /* Channel 28 In Use */
-#define                    nCIU28  0x0       
 #define                      CL29  0x7f00     /* Channel 29 Connection Label */
 #define                     CIU29  0x8000     /* Channel 29 In Use */
-#define                    nCIU29  0x0       
 #define                      CL30  0x7f0000   /* Channel 30 Connection Label */
 #define                     CIU30  0x800000   /* Channel 30 In Use */
-#define                    nCIU30  0x0       
 #define                      CL31  0x7f000000 /* Channel 31 Connection Label */
 #define                     CIU31  0x80000000 /* Channel 31 In Use */
-#define                    nCIU31  0x0       
 
 /* Bit masks for MXVR_ALLOC_8 */
 
 #define                      CL32  0x7f       /* Channel 32 Connection Label */
 #define                     CIU32  0x80       /* Channel 32 In Use */
-#define                    nCIU32  0x0       
 #define                      CL33  0x7f00     /* Channel 33 Connection Label */
 #define                     CIU33  0x8000     /* Channel 33 In Use */
-#define                    nCIU33  0x0       
 #define                      CL34  0x7f0000   /* Channel 34 Connection Label */
 #define                     CIU34  0x800000   /* Channel 34 In Use */
-#define                    nCIU34  0x0       
 #define                      CL35  0x7f000000 /* Channel 35 Connection Label */
 #define                     CIU35  0x80000000 /* Channel 35 In Use */
-#define                    nCIU35  0x0       
 
 /* Bit masks for MXVR_ALLOC_9 */
 
 #define                      CL36  0x7f       /* Channel 36 Connection Label */
 #define                     CIU36  0x80       /* Channel 36 In Use */
-#define                    nCIU36  0x0       
 #define                      CL37  0x7f00     /* Channel 37 Connection Label */
 #define                     CIU37  0x8000     /* Channel 37 In Use */
-#define                    nCIU37  0x0       
 #define                      CL38  0x7f0000   /* Channel 38 Connection Label */
 #define                     CIU38  0x800000   /* Channel 38 In Use */
-#define                    nCIU38  0x0       
 #define                      CL39  0x7f000000 /* Channel 39 Connection Label */
 #define                     CIU39  0x80000000 /* Channel 39 In Use */
-#define                    nCIU39  0x0       
 
 /* Bit masks for MXVR_ALLOC_10 */
 
 #define                      CL40  0x7f       /* Channel 40 Connection Label */
 #define                     CIU40  0x80       /* Channel 40 In Use */
-#define                    nCIU40  0x0       
 #define                      CL41  0x7f00     /* Channel 41 Connection Label */
 #define                     CIU41  0x8000     /* Channel 41 In Use */
-#define                    nCIU41  0x0       
 #define                      CL42  0x7f0000   /* Channel 42 Connection Label */
 #define                     CIU42  0x800000   /* Channel 42 In Use */
-#define                    nCIU42  0x0       
 #define                      CL43  0x7f000000 /* Channel 43 Connection Label */
 #define                     CIU43  0x80000000 /* Channel 43 In Use */
-#define                    nCIU43  0x0       
 
 /* Bit masks for MXVR_ALLOC_11 */
 
 #define                      CL44  0x7f       /* Channel 44 Connection Label */
 #define                     CIU44  0x80       /* Channel 44 In Use */
-#define                    nCIU44  0x0       
 #define                      CL45  0x7f00     /* Channel 45 Connection Label */
 #define                     CIU45  0x8000     /* Channel 45 In Use */
-#define                    nCIU45  0x0       
 #define                      CL46  0x7f0000   /* Channel 46 Connection Label */
 #define                     CIU46  0x800000   /* Channel 46 In Use */
-#define                    nCIU46  0x0       
 #define                      CL47  0x7f000000 /* Channel 47 Connection Label */
 #define                     CIU47  0x80000000 /* Channel 47 In Use */
-#define                    nCIU47  0x0       
 
 /* Bit masks for MXVR_ALLOC_12 */
 
 #define                      CL48  0x7f       /* Channel 48 Connection Label */
 #define                     CIU48  0x80       /* Channel 48 In Use */
-#define                    nCIU48  0x0       
 #define                      CL49  0x7f00     /* Channel 49 Connection Label */
 #define                     CIU49  0x8000     /* Channel 49 In Use */
-#define                    nCIU49  0x0       
 #define                      CL50  0x7f0000   /* Channel 50 Connection Label */
 #define                     CIU50  0x800000   /* Channel 50 In Use */
-#define                    nCIU50  0x0       
 #define                      CL51  0x7f000000 /* Channel 51 Connection Label */
 #define                     CIU51  0x80000000 /* Channel 51 In Use */
-#define                    nCIU51  0x0       
 
 /* Bit masks for MXVR_ALLOC_13 */
 
 #define                      CL52  0x7f       /* Channel 52 Connection Label */
 #define                     CIU52  0x80       /* Channel 52 In Use */
-#define                    nCIU52  0x0       
 #define                      CL53  0x7f00     /* Channel 53 Connection Label */
 #define                     CIU53  0x8000     /* Channel 53 In Use */
-#define                    nCIU53  0x0       
 #define                      CL54  0x7f0000   /* Channel 54 Connection Label */
 #define                     CIU54  0x800000   /* Channel 54 In Use */
-#define                    nCIU54  0x0       
 #define                      CL55  0x7f000000 /* Channel 55 Connection Label */
 #define                     CIU55  0x80000000 /* Channel 55 In Use */
-#define                    nCIU55  0x0       
 
 /* Bit masks for MXVR_ALLOC_14 */
 
 #define                      CL56  0x7f       /* Channel 56 Connection Label */
 #define                     CIU56  0x80       /* Channel 56 In Use */
-#define                    nCIU56  0x0       
 #define                      CL57  0x7f00     /* Channel 57 Connection Label */
 #define                     CIU57  0x8000     /* Channel 57 In Use */
-#define                    nCIU57  0x0       
 #define                      CL58  0x7f0000   /* Channel 58 Connection Label */
 #define                     CIU58  0x800000   /* Channel 58 In Use */
-#define                    nCIU58  0x0       
 #define                      CL59  0x7f000000 /* Channel 59 Connection Label */
 #define                     CIU59  0x80000000 /* Channel 59 In Use */
-#define                    nCIU59  0x0       
 
 /* MXVR_SYNC_LCHAN_0 Masks */
 
 /* Bit masks for MXVR_DMAx_CONFIG */
 
 #define                    MDMAEN  0x1        /* DMA Channel Enable */
-#define                   nMDMAEN  0x0       
 #define                        DD  0x2        /* DMA Channel Direction */
-#define                       nDD  0x0       
 #define                 BY4SWAPEN  0x20       /* DMA Channel Four Byte Swap Enable */
-#define                nBY4SWAPEN  0x0       
 #define                     LCHAN  0x3c0      /* DMA Channel Logical Channel */
 #define                 BITSWAPEN  0x400      /* DMA Channel Bit Swap Enable */
-#define                nBITSWAPEN  0x0       
 #define                 BY2SWAPEN  0x800      /* DMA Channel Two Byte Swap Enable */
-#define                nBY2SWAPEN  0x0       
 #define                     MFLOW  0x7000     /* DMA Channel Operation Flow */
 #define                   FIXEDPM  0x80000    /* DMA Channel Fixed Pattern Matching Select */
-#define                  nFIXEDPM  0x0       
 #define                  STARTPAT  0x300000   /* DMA Channel Start Pattern Select */
 #define                   STOPPAT  0xc00000   /* DMA Channel Stop Pattern Select */
 #define                  COUNTPOS  0x1c000000 /* DMA Channel Count Position */
 /* Bit masks for MXVR_AP_CTL */
 
 #define                   STARTAP  0x1        /* Start Asynchronous Packet Transmission */
-#define                  nSTARTAP  0x0       
 #define                  CANCELAP  0x2        /* Cancel Asynchronous Packet Transmission */
-#define                 nCANCELAP  0x0       
 #define                   RESETAP  0x4        /* Reset Asynchronous Packet Arbitration */
-#define                  nRESETAP  0x0       
 #define                    APRBE0  0x4000     /* Asynchronous Packet Receive Buffer Entry 0 */
-#define                   nAPRBE0  0x0       
 #define                    APRBE1  0x8000     /* Asynchronous Packet Receive Buffer Entry 1 */
-#define                   nAPRBE1  0x0       
 
 /* Bit masks for MXVR_APRB_START_ADDR */
 
-#define      MXVR_APRB_START_ADDR  0x1fffffe  /* Asynchronous Packet Receive Buffer Start Address */
+#define      MXVR_APRB_START_ADDR_MASK  0x1fffffe  /* Asynchronous Packet Receive Buffer Start Address */
 
 /* Bit masks for MXVR_APRB_CURR_ADDR */
 
-#define       MXVR_APRB_CURR_ADDR  0xffffffff /* Asynchronous Packet Receive Buffer Current Address */
+#define       MXVR_APRB_CURR_ADDR_MASK  0xffffffff /* Asynchronous Packet Receive Buffer Current Address */
 
 /* Bit masks for MXVR_APTB_START_ADDR */
 
-#define       MXVR_APTB_START_ADDR  0x1fffffe  /* Asynchronous Packet Transmit Buffer Start Address */
+#define       MXVR_APTB_START_ADDR_MASK  0x1fffffe  /* Asynchronous Packet Transmit Buffer Start Address */
 
 /* Bit masks for MXVR_APTB_CURR_ADDR */
 
-#define        MXVR_APTB_CURR_ADDR  0xffffffff /* Asynchronous Packet Transmit Buffer Current Address */
+#define        MXVR_APTB_CURR_ADDR_MASK  0xffffffff /* Asynchronous Packet Transmit Buffer Current Address */
 
 /* Bit masks for MXVR_CM_CTL */
 
 #define                   STARTCM  0x1        /* Start Control Message Transmission */
-#define                  nSTARTCM  0x0       
 #define                  CANCELCM  0x2        /* Cancel Control Message Transmission */
-#define                 nCANCELCM  0x0       
 #define                    CMRBE0  0x10000    /* Control Message Receive Buffer Entry 0 */
-#define                   nCMRBE0  0x0       
 #define                    CMRBE1  0x20000    /* Control Message Receive Buffer Entry 1 */
-#define                   nCMRBE1  0x0       
 #define                    CMRBE2  0x40000    /* Control Message Receive Buffer Entry 2 */
-#define                   nCMRBE2  0x0       
 #define                    CMRBE3  0x80000    /* Control Message Receive Buffer Entry 3 */
-#define                   nCMRBE3  0x0       
 #define                    CMRBE4  0x100000   /* Control Message Receive Buffer Entry 4 */
-#define                   nCMRBE4  0x0       
 #define                    CMRBE5  0x200000   /* Control Message Receive Buffer Entry 5 */
-#define                   nCMRBE5  0x0       
 #define                    CMRBE6  0x400000   /* Control Message Receive Buffer Entry 6 */
-#define                   nCMRBE6  0x0       
 #define                    CMRBE7  0x800000   /* Control Message Receive Buffer Entry 7 */
-#define                   nCMRBE7  0x0       
 #define                    CMRBE8  0x1000000  /* Control Message Receive Buffer Entry 8 */
-#define                   nCMRBE8  0x0       
 #define                    CMRBE9  0x2000000  /* Control Message Receive Buffer Entry 9 */
-#define                   nCMRBE9  0x0       
 #define                   CMRBE10  0x4000000  /* Control Message Receive Buffer Entry 10 */
-#define                  nCMRBE10  0x0       
 #define                   CMRBE11  0x8000000  /* Control Message Receive Buffer Entry 11 */
-#define                  nCMRBE11  0x0       
 #define                   CMRBE12  0x10000000 /* Control Message Receive Buffer Entry 12 */
-#define                  nCMRBE12  0x0       
 #define                   CMRBE13  0x20000000 /* Control Message Receive Buffer Entry 13 */
-#define                  nCMRBE13  0x0       
 #define                   CMRBE14  0x40000000 /* Control Message Receive Buffer Entry 14 */
-#define                  nCMRBE14  0x0       
 #define                   CMRBE15  0x80000000 /* Control Message Receive Buffer Entry 15 */
-#define                  nCMRBE15  0x0       
 
 /* Bit masks for MXVR_CMRB_START_ADDR */
 
-#define      MXVR_CMRB_START_ADDR  0x1fffffe  /* Control Message Receive Buffer Start Address */
+#define      MXVR_CMRB_START_ADDR_MASK  0x1fffffe  /* Control Message Receive Buffer Start Address */
 
 /* Bit masks for MXVR_CMRB_CURR_ADDR */
 
-#define       MXVR_CMRB_CURR_ADDR  0xffffffff /* Control Message Receive Buffer Current Address */
+#define       MXVR_CMRB_CURR_ADDR_MASK  0xffffffff /* Control Message Receive Buffer Current Address */
 
 /* Bit masks for MXVR_CMTB_START_ADDR */
 
-#define      MXVR_CMTB_START_ADDR  0x1fffffe  /* Control Message Transmit Buffer Start Address */
+#define      MXVR_CMTB_START_ADDR_MASK  0x1fffffe  /* Control Message Transmit Buffer Start Address */
 
 /* Bit masks for MXVR_CMTB_CURR_ADDR */
 
-#define       MXVR_CMTB_CURR_ADDR  0xffffffff /* Control Message Transmit Buffer Current Address */
+#define       MXVR_CMTB_CURR_ADDR_MASK  0xffffffff /* Control Message Transmit Buffer Current Address */
 
 /* Bit masks for MXVR_RRDB_START_ADDR */
 
-#define      MXVR_RRDB_START_ADDR  0x1fffffe  /* Remote Read Buffer Start Address */
+#define      MXVR_RRDB_START_ADDR_MASK  0x1fffffe  /* Remote Read Buffer Start Address */
 
 /* Bit masks for MXVR_RRDB_CURR_ADDR */
 
-#define       MXVR_RRDB_CURR_ADDR  0xffffffff /* Remote Read Buffer Current Address */
+#define       MXVR_RRDB_CURR_ADDR_MASK  0xffffffff /* Remote Read Buffer Current Address */
 
 /* Bit masks for MXVR_PAT_DATAx */
 
 /* Bit masks for MXVR_PAT_EN_0 */
 
 #define              MATCH_EN_0_0  0x1        /* Pattern Match Enable Byte 0 Bit 0 */
-#define             nMATCH_EN_0_0  0x0       
 #define              MATCH_EN_0_1  0x2        /* Pattern Match Enable Byte 0 Bit 1 */
-#define             nMATCH_EN_0_1  0x0       
 #define              MATCH_EN_0_2  0x4        /* Pattern Match Enable Byte 0 Bit 2 */
-#define             nMATCH_EN_0_2  0x0       
 #define              MATCH_EN_0_3  0x8        /* Pattern Match Enable Byte 0 Bit 3 */
-#define             nMATCH_EN_0_3  0x0       
 #define              MATCH_EN_0_4  0x10       /* Pattern Match Enable Byte 0 Bit 4 */
-#define             nMATCH_EN_0_4  0x0       
 #define              MATCH_EN_0_5  0x20       /* Pattern Match Enable Byte 0 Bit 5 */
-#define             nMATCH_EN_0_5  0x0       
 #define              MATCH_EN_0_6  0x40       /* Pattern Match Enable Byte 0 Bit 6 */
-#define             nMATCH_EN_0_6  0x0       
 #define              MATCH_EN_0_7  0x80       /* Pattern Match Enable Byte 0 Bit 7 */
-#define             nMATCH_EN_0_7  0x0       
 #define              MATCH_EN_1_0  0x100      /* Pattern Match Enable Byte 1 Bit 0 */
-#define             nMATCH_EN_1_0  0x0       
 #define              MATCH_EN_1_1  0x200      /* Pattern Match Enable Byte 1 Bit 1 */
-#define             nMATCH_EN_1_1  0x0       
 #define              MATCH_EN_1_2  0x400      /* Pattern Match Enable Byte 1 Bit 2 */
-#define             nMATCH_EN_1_2  0x0       
 #define              MATCH_EN_1_3  0x800      /* Pattern Match Enable Byte 1 Bit 3 */
-#define             nMATCH_EN_1_3  0x0       
 #define              MATCH_EN_1_4  0x1000     /* Pattern Match Enable Byte 1 Bit 4 */
-#define             nMATCH_EN_1_4  0x0       
 #define              MATCH_EN_1_5  0x2000     /* Pattern Match Enable Byte 1 Bit 5 */
-#define             nMATCH_EN_1_5  0x0       
 #define              MATCH_EN_1_6  0x4000     /* Pattern Match Enable Byte 1 Bit 6 */
-#define             nMATCH_EN_1_6  0x0       
 #define              MATCH_EN_1_7  0x8000     /* Pattern Match Enable Byte 1 Bit 7 */
-#define             nMATCH_EN_1_7  0x0       
 #define              MATCH_EN_2_0  0x10000    /* Pattern Match Enable Byte 2 Bit 0 */
-#define             nMATCH_EN_2_0  0x0       
 #define              MATCH_EN_2_1  0x20000    /* Pattern Match Enable Byte 2 Bit 1 */
-#define             nMATCH_EN_2_1  0x0       
 #define              MATCH_EN_2_2  0x40000    /* Pattern Match Enable Byte 2 Bit 2 */
-#define             nMATCH_EN_2_2  0x0       
 #define              MATCH_EN_2_3  0x80000    /* Pattern Match Enable Byte 2 Bit 3 */
-#define             nMATCH_EN_2_3  0x0       
 #define              MATCH_EN_2_4  0x100000   /* Pattern Match Enable Byte 2 Bit 4 */
-#define             nMATCH_EN_2_4  0x0       
 #define              MATCH_EN_2_5  0x200000   /* Pattern Match Enable Byte 2 Bit 5 */
-#define             nMATCH_EN_2_5  0x0       
 #define              MATCH_EN_2_6  0x400000   /* Pattern Match Enable Byte 2 Bit 6 */
-#define             nMATCH_EN_2_6  0x0       
 #define              MATCH_EN_2_7  0x800000   /* Pattern Match Enable Byte 2 Bit 7 */
-#define             nMATCH_EN_2_7  0x0       
 #define              MATCH_EN_3_0  0x1000000  /* Pattern Match Enable Byte 3 Bit 0 */
-#define             nMATCH_EN_3_0  0x0       
 #define              MATCH_EN_3_1  0x2000000  /* Pattern Match Enable Byte 3 Bit 1 */
-#define             nMATCH_EN_3_1  0x0       
 #define              MATCH_EN_3_2  0x4000000  /* Pattern Match Enable Byte 3 Bit 2 */
-#define             nMATCH_EN_3_2  0x0       
 #define              MATCH_EN_3_3  0x8000000  /* Pattern Match Enable Byte 3 Bit 3 */
-#define             nMATCH_EN_3_3  0x0       
 #define              MATCH_EN_3_4  0x10000000 /* Pattern Match Enable Byte 3 Bit 4 */
-#define             nMATCH_EN_3_4  0x0       
 #define              MATCH_EN_3_5  0x20000000 /* Pattern Match Enable Byte 3 Bit 5 */
-#define             nMATCH_EN_3_5  0x0       
 #define              MATCH_EN_3_6  0x40000000 /* Pattern Match Enable Byte 3 Bit 6 */
-#define             nMATCH_EN_3_6  0x0       
 #define              MATCH_EN_3_7  0x80000000 /* Pattern Match Enable Byte 3 Bit 7 */
-#define             nMATCH_EN_3_7  0x0       
 
 /* Bit masks for MXVR_PAT_EN_1 */
 
 #define              MATCH_EN_0_0  0x1        /* Pattern Match Enable Byte 0 Bit 0 */
-#define             nMATCH_EN_0_0  0x0       
 #define              MATCH_EN_0_1  0x2        /* Pattern Match Enable Byte 0 Bit 1 */
-#define             nMATCH_EN_0_1  0x0       
 #define              MATCH_EN_0_2  0x4        /* Pattern Match Enable Byte 0 Bit 2 */
-#define             nMATCH_EN_0_2  0x0       
 #define              MATCH_EN_0_3  0x8        /* Pattern Match Enable Byte 0 Bit 3 */
-#define             nMATCH_EN_0_3  0x0       
 #define              MATCH_EN_0_4  0x10       /* Pattern Match Enable Byte 0 Bit 4 */
-#define             nMATCH_EN_0_4  0x0       
 #define              MATCH_EN_0_5  0x20       /* Pattern Match Enable Byte 0 Bit 5 */
-#define             nMATCH_EN_0_5  0x0       
 #define              MATCH_EN_0_6  0x40       /* Pattern Match Enable Byte 0 Bit 6 */
-#define             nMATCH_EN_0_6  0x0       
 #define              MATCH_EN_0_7  0x80       /* Pattern Match Enable Byte 0 Bit 7 */
-#define             nMATCH_EN_0_7  0x0       
 #define              MATCH_EN_1_0  0x100      /* Pattern Match Enable Byte 1 Bit 0 */
-#define             nMATCH_EN_1_0  0x0       
 #define              MATCH_EN_1_1  0x200      /* Pattern Match Enable Byte 1 Bit 1 */
-#define             nMATCH_EN_1_1  0x0       
 #define              MATCH_EN_1_2  0x400      /* Pattern Match Enable Byte 1 Bit 2 */
-#define             nMATCH_EN_1_2  0x0       
 #define              MATCH_EN_1_3  0x800      /* Pattern Match Enable Byte 1 Bit 3 */
-#define             nMATCH_EN_1_3  0x0       
 #define              MATCH_EN_1_4  0x1000     /* Pattern Match Enable Byte 1 Bit 4 */
-#define             nMATCH_EN_1_4  0x0       
 #define              MATCH_EN_1_5  0x2000     /* Pattern Match Enable Byte 1 Bit 5 */
-#define             nMATCH_EN_1_5  0x0       
 #define              MATCH_EN_1_6  0x4000     /* Pattern Match Enable Byte 1 Bit 6 */
-#define             nMATCH_EN_1_6  0x0       
 #define              MATCH_EN_1_7  0x8000     /* Pattern Match Enable Byte 1 Bit 7 */
-#define             nMATCH_EN_1_7  0x0       
 #define              MATCH_EN_2_0  0x10000    /* Pattern Match Enable Byte 2 Bit 0 */
-#define             nMATCH_EN_2_0  0x0       
 #define              MATCH_EN_2_1  0x20000    /* Pattern Match Enable Byte 2 Bit 1 */
-#define             nMATCH_EN_2_1  0x0       
 #define              MATCH_EN_2_2  0x40000    /* Pattern Match Enable Byte 2 Bit 2 */
-#define             nMATCH_EN_2_2  0x0       
 #define              MATCH_EN_2_3  0x80000    /* Pattern Match Enable Byte 2 Bit 3 */
-#define             nMATCH_EN_2_3  0x0       
 #define              MATCH_EN_2_4  0x100000   /* Pattern Match Enable Byte 2 Bit 4 */
-#define             nMATCH_EN_2_4  0x0       
 #define              MATCH_EN_2_5  0x200000   /* Pattern Match Enable Byte 2 Bit 5 */
-#define             nMATCH_EN_2_5  0x0       
 #define              MATCH_EN_2_6  0x400000   /* Pattern Match Enable Byte 2 Bit 6 */
-#define             nMATCH_EN_2_6  0x0       
 #define              MATCH_EN_2_7  0x800000   /* Pattern Match Enable Byte 2 Bit 7 */
-#define             nMATCH_EN_2_7  0x0       
 #define              MATCH_EN_3_0  0x1000000  /* Pattern Match Enable Byte 3 Bit 0 */
-#define             nMATCH_EN_3_0  0x0       
 #define              MATCH_EN_3_1  0x2000000  /* Pattern Match Enable Byte 3 Bit 1 */
-#define             nMATCH_EN_3_1  0x0       
 #define              MATCH_EN_3_2  0x4000000  /* Pattern Match Enable Byte 3 Bit 2 */
-#define             nMATCH_EN_3_2  0x0       
 #define              MATCH_EN_3_3  0x8000000  /* Pattern Match Enable Byte 3 Bit 3 */
-#define             nMATCH_EN_3_3  0x0       
 #define              MATCH_EN_3_4  0x10000000 /* Pattern Match Enable Byte 3 Bit 4 */
-#define             nMATCH_EN_3_4  0x0       
 #define              MATCH_EN_3_5  0x20000000 /* Pattern Match Enable Byte 3 Bit 5 */
-#define             nMATCH_EN_3_5  0x0       
 #define              MATCH_EN_3_6  0x40000000 /* Pattern Match Enable Byte 3 Bit 6 */
-#define             nMATCH_EN_3_6  0x0       
 #define              MATCH_EN_3_7  0x80000000 /* Pattern Match Enable Byte 3 Bit 7 */
-#define             nMATCH_EN_3_7  0x0       
 
 /* Bit masks for MXVR_FRAME_CNT_0 */
 
 
 #define                    TX_CH0  0x3f       /* Transmit Channel 0 */
 #define                  MUTE_CH0  0x80       /* Mute Channel 0 */
-#define                 nMUTE_CH0  0x0       
 #define                    TX_CH1  0x3f00     /* Transmit Channel 0 */
 #define                  MUTE_CH1  0x8000     /* Mute Channel 0 */
-#define                 nMUTE_CH1  0x0       
 #define                    TX_CH2  0x3f0000   /* Transmit Channel 0 */
 #define                  MUTE_CH2  0x800000   /* Mute Channel 0 */
-#define                 nMUTE_CH2  0x0       
 #define                    TX_CH3  0x3f000000 /* Transmit Channel 0 */
 #define                  MUTE_CH3  0x80000000 /* Mute Channel 0 */
-#define                 nMUTE_CH3  0x0       
 
 /* Bit masks for MXVR_ROUTING_1 */
 
 #define                    TX_CH4  0x3f       /* Transmit Channel 4 */
 #define                  MUTE_CH4  0x80       /* Mute Channel 4 */
-#define                 nMUTE_CH4  0x0       
 #define                    TX_CH5  0x3f00     /* Transmit Channel 5 */
 #define                  MUTE_CH5  0x8000     /* Mute Channel 5 */
-#define                 nMUTE_CH5  0x0       
 #define                    TX_CH6  0x3f0000   /* Transmit Channel 6 */
 #define                  MUTE_CH6  0x800000   /* Mute Channel 6 */
-#define                 nMUTE_CH6  0x0       
 #define                    TX_CH7  0x3f000000 /* Transmit Channel 7 */
 #define                  MUTE_CH7  0x80000000 /* Mute Channel 7 */
-#define                 nMUTE_CH7  0x0       
 
 /* Bit masks for MXVR_ROUTING_2 */
 
 #define                    TX_CH8  0x3f       /* Transmit Channel 8 */
 #define                  MUTE_CH8  0x80       /* Mute Channel 8 */
-#define                 nMUTE_CH8  0x0       
 #define                    TX_CH9  0x3f00     /* Transmit Channel 9 */
 #define                  MUTE_CH9  0x8000     /* Mute Channel 9 */
-#define                 nMUTE_CH9  0x0       
 #define                   TX_CH10  0x3f0000   /* Transmit Channel 10 */
 #define                 MUTE_CH10  0x800000   /* Mute Channel 10 */
-#define                nMUTE_CH10  0x0       
 #define                   TX_CH11  0x3f000000 /* Transmit Channel 11 */
 #define                 MUTE_CH11  0x80000000 /* Mute Channel 11 */
-#define                nMUTE_CH11  0x0       
 
 /* Bit masks for MXVR_ROUTING_3 */
 
 #define                   TX_CH12  0x3f       /* Transmit Channel 12 */
 #define                 MUTE_CH12  0x80       /* Mute Channel 12 */
-#define                nMUTE_CH12  0x0       
 #define                   TX_CH13  0x3f00     /* Transmit Channel 13 */
 #define                 MUTE_CH13  0x8000     /* Mute Channel 13 */
-#define                nMUTE_CH13  0x0       
 #define                   TX_CH14  0x3f0000   /* Transmit Channel 14 */
 #define                 MUTE_CH14  0x800000   /* Mute Channel 14 */
-#define                nMUTE_CH14  0x0       
 #define                   TX_CH15  0x3f000000 /* Transmit Channel 15 */
 #define                 MUTE_CH15  0x80000000 /* Mute Channel 15 */
-#define                nMUTE_CH15  0x0       
 
 /* Bit masks for MXVR_ROUTING_4 */
 
 #define                   TX_CH16  0x3f       /* Transmit Channel 16 */
 #define                 MUTE_CH16  0x80       /* Mute Channel 16 */
-#define                nMUTE_CH16  0x0       
 #define                   TX_CH17  0x3f00     /* Transmit Channel 17 */
 #define                 MUTE_CH17  0x8000     /* Mute Channel 17 */
-#define                nMUTE_CH17  0x0       
 #define                   TX_CH18  0x3f0000   /* Transmit Channel 18 */
 #define                 MUTE_CH18  0x800000   /* Mute Channel 18 */
-#define                nMUTE_CH18  0x0       
 #define                   TX_CH19  0x3f000000 /* Transmit Channel 19 */
 #define                 MUTE_CH19  0x80000000 /* Mute Channel 19 */
-#define                nMUTE_CH19  0x0       
 
 /* Bit masks for MXVR_ROUTING_5 */
 
 #define                   TX_CH20  0x3f       /* Transmit Channel 20 */
 #define                 MUTE_CH20  0x80       /* Mute Channel 20 */
-#define                nMUTE_CH20  0x0       
 #define                   TX_CH21  0x3f00     /* Transmit Channel 21 */
 #define                 MUTE_CH21  0x8000     /* Mute Channel 21 */
-#define                nMUTE_CH21  0x0       
 #define                   TX_CH22  0x3f0000   /* Transmit Channel 22 */
 #define                 MUTE_CH22  0x800000   /* Mute Channel 22 */
-#define                nMUTE_CH22  0x0       
 #define                   TX_CH23  0x3f000000 /* Transmit Channel 23 */
 #define                 MUTE_CH23  0x80000000 /* Mute Channel 23 */
-#define                nMUTE_CH23  0x0       
 
 /* Bit masks for MXVR_ROUTING_6 */
 
 #define                   TX_CH24  0x3f       /* Transmit Channel 24 */
 #define                 MUTE_CH24  0x80       /* Mute Channel 24 */
-#define                nMUTE_CH24  0x0       
 #define                   TX_CH25  0x3f00     /* Transmit Channel 25 */
 #define                 MUTE_CH25  0x8000     /* Mute Channel 25 */
-#define                nMUTE_CH25  0x0       
 #define                   TX_CH26  0x3f0000   /* Transmit Channel 26 */
 #define                 MUTE_CH26  0x800000   /* Mute Channel 26 */
-#define                nMUTE_CH26  0x0       
 #define                   TX_CH27  0x3f000000 /* Transmit Channel 27 */
 #define                 MUTE_CH27  0x80000000 /* Mute Channel 27 */
-#define                nMUTE_CH27  0x0       
 
 /* Bit masks for MXVR_ROUTING_7 */
 
 #define                   TX_CH28  0x3f       /* Transmit Channel 28 */
 #define                 MUTE_CH28  0x80       /* Mute Channel 28 */
-#define                nMUTE_CH28  0x0       
 #define                   TX_CH29  0x3f00     /* Transmit Channel 29 */
 #define                 MUTE_CH29  0x8000     /* Mute Channel 29 */
-#define                nMUTE_CH29  0x0       
 #define                   TX_CH30  0x3f0000   /* Transmit Channel 30 */
 #define                 MUTE_CH30  0x800000   /* Mute Channel 30 */
-#define                nMUTE_CH30  0x0       
 #define                   TX_CH31  0x3f000000 /* Transmit Channel 31 */
 #define                 MUTE_CH31  0x80000000 /* Mute Channel 31 */
-#define                nMUTE_CH31  0x0       
 
 /* Bit masks for MXVR_ROUTING_8 */
 
 #define                   TX_CH32  0x3f       /* Transmit Channel 32 */
 #define                 MUTE_CH32  0x80       /* Mute Channel 32 */
-#define                nMUTE_CH32  0x0       
 #define                   TX_CH33  0x3f00     /* Transmit Channel 33 */
 #define                 MUTE_CH33  0x8000     /* Mute Channel 33 */
-#define                nMUTE_CH33  0x0       
 #define                   TX_CH34  0x3f0000   /* Transmit Channel 34 */
 #define                 MUTE_CH34  0x800000   /* Mute Channel 34 */
-#define                nMUTE_CH34  0x0       
 #define                   TX_CH35  0x3f000000 /* Transmit Channel 35 */
 #define                 MUTE_CH35  0x80000000 /* Mute Channel 35 */
-#define                nMUTE_CH35  0x0       
 
 /* Bit masks for MXVR_ROUTING_9 */
 
 #define                   TX_CH36  0x3f       /* Transmit Channel 36 */
 #define                 MUTE_CH36  0x80       /* Mute Channel 36 */
-#define                nMUTE_CH36  0x0       
 #define                   TX_CH37  0x3f00     /* Transmit Channel 37 */
 #define                 MUTE_CH37  0x8000     /* Mute Channel 37 */
-#define                nMUTE_CH37  0x0       
 #define                   TX_CH38  0x3f0000   /* Transmit Channel 38 */
 #define                 MUTE_CH38  0x800000   /* Mute Channel 38 */
-#define                nMUTE_CH38  0x0       
 #define                   TX_CH39  0x3f000000 /* Transmit Channel 39 */
 #define                 MUTE_CH39  0x80000000 /* Mute Channel 39 */
-#define                nMUTE_CH39  0x0       
 
 /* Bit masks for MXVR_ROUTING_10 */
 
 #define                   TX_CH40  0x3f       /* Transmit Channel 40 */
 #define                 MUTE_CH40  0x80       /* Mute Channel 40 */
-#define                nMUTE_CH40  0x0       
 #define                   TX_CH41  0x3f00     /* Transmit Channel 41 */
 #define                 MUTE_CH41  0x8000     /* Mute Channel 41 */
-#define                nMUTE_CH41  0x0       
 #define                   TX_CH42  0x3f0000   /* Transmit Channel 42 */
 #define                 MUTE_CH42  0x800000   /* Mute Channel 42 */
-#define                nMUTE_CH42  0x0       
 #define                   TX_CH43  0x3f000000 /* Transmit Channel 43 */
 #define                 MUTE_CH43  0x80000000 /* Mute Channel 43 */
-#define                nMUTE_CH43  0x0       
 
 /* Bit masks for MXVR_ROUTING_11 */
 
 #define                   TX_CH44  0x3f       /* Transmit Channel 44 */
 #define                 MUTE_CH44  0x80       /* Mute Channel 44 */
-#define                nMUTE_CH44  0x0       
 #define                   TX_CH45  0x3f00     /* Transmit Channel 45 */
 #define                 MUTE_CH45  0x8000     /* Mute Channel 45 */
-#define                nMUTE_CH45  0x0       
 #define                   TX_CH46  0x3f0000   /* Transmit Channel 46 */
 #define                 MUTE_CH46  0x800000   /* Mute Channel 46 */
-#define                nMUTE_CH46  0x0       
 #define                   TX_CH47  0x3f000000 /* Transmit Channel 47 */
 #define                 MUTE_CH47  0x80000000 /* Mute Channel 47 */
-#define                nMUTE_CH47  0x0       
 
 /* Bit masks for MXVR_ROUTING_12 */
 
 #define                   TX_CH48  0x3f       /* Transmit Channel 48 */
 #define                 MUTE_CH48  0x80       /* Mute Channel 48 */
-#define                nMUTE_CH48  0x0       
 #define                   TX_CH49  0x3f00     /* Transmit Channel 49 */
 #define                 MUTE_CH49  0x8000     /* Mute Channel 49 */
-#define                nMUTE_CH49  0x0       
 #define                   TX_CH50  0x3f0000   /* Transmit Channel 50 */
 #define                 MUTE_CH50  0x800000   /* Mute Channel 50 */
-#define                nMUTE_CH50  0x0       
 #define                   TX_CH51  0x3f000000 /* Transmit Channel 51 */
 #define                 MUTE_CH51  0x80000000 /* Mute Channel 51 */
-#define                nMUTE_CH51  0x0       
 
 /* Bit masks for MXVR_ROUTING_13 */
 
 #define                   TX_CH52  0x3f       /* Transmit Channel 52 */
 #define                 MUTE_CH52  0x80       /* Mute Channel 52 */
-#define                nMUTE_CH52  0x0       
 #define                   TX_CH53  0x3f00     /* Transmit Channel 53 */
 #define                 MUTE_CH53  0x8000     /* Mute Channel 53 */
-#define                nMUTE_CH53  0x0       
 #define                   TX_CH54  0x3f0000   /* Transmit Channel 54 */
 #define                 MUTE_CH54  0x800000   /* Mute Channel 54 */
-#define                nMUTE_CH54  0x0       
 #define                   TX_CH55  0x3f000000 /* Transmit Channel 55 */
 #define                 MUTE_CH55  0x80000000 /* Mute Channel 55 */
-#define                nMUTE_CH55  0x0       
 
 /* Bit masks for MXVR_ROUTING_14 */
 
 #define                   TX_CH56  0x3f       /* Transmit Channel 56 */
 #define                 MUTE_CH56  0x80       /* Mute Channel 56 */
-#define                nMUTE_CH56  0x0       
 #define                   TX_CH57  0x3f00     /* Transmit Channel 57 */
 #define                 MUTE_CH57  0x8000     /* Mute Channel 57 */
-#define                nMUTE_CH57  0x0       
 #define                   TX_CH58  0x3f0000   /* Transmit Channel 58 */
 #define                 MUTE_CH58  0x800000   /* Mute Channel 58 */
-#define                nMUTE_CH58  0x0       
 #define                   TX_CH59  0x3f000000 /* Transmit Channel 59 */
 #define                 MUTE_CH59  0x80000000 /* Mute Channel 59 */
-#define                nMUTE_CH59  0x0       
 
 /* Bit masks for MXVR_BLOCK_CNT */
 
 /* Bit masks for MXVR_CLK_CTL */
 
 #define                  MXTALCEN  0x1        /* MXVR Crystal Oscillator Clock Enable */
-#define                 nMXTALCEN  0x0       
 #define                  MXTALFEN  0x2        /* MXVR Crystal Oscillator Feedback Enable */
-#define                 nMXTALFEN  0x0       
 #define                  MXTALMUL  0x30       /* MXVR Crystal Multiplier */
 #define                  CLKX3SEL  0x80       /* Clock Generation Source Select */
-#define                 nCLKX3SEL  0x0       
 #define                   MMCLKEN  0x100      /* Master Clock Enable */
-#define                  nMMCLKEN  0x0       
 #define                  MMCLKMUL  0x1e00     /* Master Clock Multiplication Factor */
 #define                   PLLSMPS  0xe000     /* MXVR PLL State Machine Prescaler */
 #define                   MBCLKEN  0x10000    /* Bit Clock Enable */
-#define                  nMBCLKEN  0x0       
 #define                  MBCLKDIV  0x1e0000   /* Bit Clock Divide Factor */
 #define                     INVRX  0x800000   /* Invert Receive Data */
-#define                    nINVRX  0x0       
 #define                     MFSEN  0x1000000  /* Frame Sync Enable */
-#define                    nMFSEN  0x0       
 #define                    MFSDIV  0x1e000000 /* Frame Sync Divide Factor */
 #define                    MFSSEL  0x60000000 /* Frame Sync Select */
 #define                   MFSSYNC  0x80000000 /* Frame Sync Synchronization Select */
-#define                  nMFSSYNC  0x0       
 
 /* Bit masks for MXVR_CDRPLL_CTL */
 
 #define                   CDRSMEN  0x1        /* MXVR CDRPLL State Machine Enable */
-#define                  nCDRSMEN  0x0       
 #define                   CDRRSTB  0x2        /* MXVR CDRPLL Reset */
-#define                  nCDRRSTB  0x0       
 #define                   CDRSVCO  0x4        /* MXVR CDRPLL Start VCO */
-#define                  nCDRSVCO  0x0       
 #define                   CDRMODE  0x8        /* MXVR CDRPLL CDR Mode Select */
-#define                  nCDRMODE  0x0       
 #define                   CDRSCNT  0x3f0      /* MXVR CDRPLL Start Counter */
 #define                   CDRLCNT  0xfc00     /* MXVR CDRPLL Lock Counter */
 #define                 CDRSHPSEL  0x3f0000   /* MXVR CDRPLL Shaper Select */
 #define                  CDRSHPEN  0x800000   /* MXVR CDRPLL Shaper Enable */
-#define                 nCDRSHPEN  0x0       
 #define                  CDRCPSEL  0xff000000 /* MXVR CDRPLL Charge Pump Current Select */
 
 /* Bit masks for MXVR_FMPLL_CTL */
 
 #define                    FMSMEN  0x1        /* MXVR FMPLL State Machine Enable */
-#define                   nFMSMEN  0x0       
 #define                    FMRSTB  0x2        /* MXVR FMPLL Reset */
-#define                   nFMRSTB  0x0       
 #define                    FMSVCO  0x4        /* MXVR FMPLL Start VCO */
-#define                   nFMSVCO  0x0       
 #define                    FMSCNT  0x3f0      /* MXVR FMPLL Start Counter */
 #define                    FMLCNT  0xfc00     /* MXVR FMPLL Lock Counter */
 #define                   FMCPSEL  0xff000000 /* MXVR FMPLL Charge Pump Current Select */
 /* Bit masks for MXVR_PIN_CTL */
 
 #define                  MTXONBOD  0x1        /* MTXONB Open Drain Select */
-#define                 nMTXONBOD  0x0       
 #define                   MTXONBG  0x2        /* MTXONB Gates MTX Select */
-#define                  nMTXONBG  0x0       
 #define                     MFSOE  0x10       /* MFS Output Enable */
-#define                    nMFSOE  0x0       
 #define                  MFSGPSEL  0x20       /* MFS General Purpose Output Select */
-#define                 nMFSGPSEL  0x0       
 #define                  MFSGPDAT  0x40       /* MFS General Purpose Output Data */
-#define                 nMFSGPDAT  0x0       
 
 /* Bit masks for MXVR_SCLK_CNT */
 
 /* Bit masks for KPAD_CTL */
 
 #define                   KPAD_EN  0x1        /* Keypad Enable */
-#define                  nKPAD_EN  0x0       
 #define              KPAD_IRQMODE  0x6        /* Key Press Interrupt Enable */
 #define                KPAD_ROWEN  0x1c00     /* Row Enable Width */
 #define                KPAD_COLEN  0xe000     /* Column Enable Width */
 /* Bit masks for KPAD_STAT */
 
 #define                  KPAD_IRQ  0x1        /* Keypad Interrupt Status */
-#define                 nKPAD_IRQ  0x0       
 #define              KPAD_MROWCOL  0x6        /* Multiple Row/Column Keypress Status */
 #define              KPAD_PRESSED  0x8        /* Key press current status */
-#define             nKPAD_PRESSED  0x0       
 
 /* Bit masks for KPAD_SOFTEVAL */
 
 #define           KPAD_SOFTEVAL_E  0x2        /* Software Programmable Force Evaluate */
-#define          nKPAD_SOFTEVAL_E  0x0       
 
 /* Bit masks for SDH_COMMAND */
 
 #define                   CMD_IDX  0x3f       /* Command Index */
 #define                   CMD_RSP  0x40       /* Response */
-#define                  nCMD_RSP  0x0       
 #define                 CMD_L_RSP  0x80       /* Long Response */
-#define                nCMD_L_RSP  0x0       
 #define                 CMD_INT_E  0x100      /* Command Interrupt */
-#define                nCMD_INT_E  0x0       
 #define                CMD_PEND_E  0x200      /* Command Pending */
-#define               nCMD_PEND_E  0x0       
 #define                     CMD_E  0x400      /* Command Enable */
-#define                    nCMD_E  0x0       
 
 /* Bit masks for SDH_PWR_CTL */
 
 #define                       TBD  0x3c       /* TBD */
 #endif
 #define                 SD_CMD_OD  0x40       /* Open Drain Output */
-#define                nSD_CMD_OD  0x0       
 #define                   ROD_CTL  0x80       /* Rod Control */
-#define                  nROD_CTL  0x0       
 
 /* Bit masks for SDH_CLK_CTL */
 
 #define                    CLKDIV  0xff       /* MC_CLK Divisor */
 #define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
-#define                    nCLK_E  0x0       
 #define                  PWR_SV_E  0x200      /* Power Save Enable */
-#define                 nPWR_SV_E  0x0       
 #define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
-#define            nCLKDIV_BYPASS  0x0       
 #define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
-#define                 nWIDE_BUS  0x0       
 
 /* Bit masks for SDH_RESP_CMD */
 
 /* Bit masks for SDH_DATA_CTL */
 
 #define                     DTX_E  0x1        /* Data Transfer Enable */
-#define                    nDTX_E  0x0       
 #define                   DTX_DIR  0x2        /* Data Transfer Direction */
-#define                  nDTX_DIR  0x0       
 #define                  DTX_MODE  0x4        /* Data Transfer Mode */
-#define                 nDTX_MODE  0x0       
 #define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
-#define                nDTX_DMA_E  0x0       
 #define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
 
 /* Bit masks for SDH_STATUS */
 
 #define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
-#define             nCMD_CRC_FAIL  0x0       
 #define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
-#define             nDAT_CRC_FAIL  0x0       
-#define               CMD_TIMEOUT  0x4        /* CMD Time Out */
-#define              nCMD_TIMEOUT  0x0       
-#define               DAT_TIMEOUT  0x8        /* Data Time Out */
-#define              nDAT_TIMEOUT  0x0       
+#define               CMD_TIME_OUT  0x4        /* CMD Time Out */
+#define               DAT_TIME_OUT  0x8        /* Data Time Out */
 #define               TX_UNDERRUN  0x10       /* Transmit Underrun */
-#define              nTX_UNDERRUN  0x0       
 #define                RX_OVERRUN  0x20       /* Receive Overrun */
-#define               nRX_OVERRUN  0x0       
 #define              CMD_RESP_END  0x40       /* CMD Response End */
-#define             nCMD_RESP_END  0x0       
 #define                  CMD_SENT  0x80       /* CMD Sent */
-#define                 nCMD_SENT  0x0       
 #define                   DAT_END  0x100      /* Data End */
-#define                  nDAT_END  0x0       
 #define             START_BIT_ERR  0x200      /* Start Bit Error */
-#define            nSTART_BIT_ERR  0x0       
 #define               DAT_BLK_END  0x400      /* Data Block End */
-#define              nDAT_BLK_END  0x0       
 #define                   CMD_ACT  0x800      /* CMD Active */
-#define                  nCMD_ACT  0x0       
 #define                    TX_ACT  0x1000     /* Transmit Active */
-#define                   nTX_ACT  0x0       
 #define                    RX_ACT  0x2000     /* Receive Active */
-#define                   nRX_ACT  0x0       
 #define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
-#define             nTX_FIFO_STAT  0x0       
 #define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
-#define             nRX_FIFO_STAT  0x0       
 #define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
-#define             nTX_FIFO_FULL  0x0       
 #define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
-#define             nRX_FIFO_FULL  0x0       
 #define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
-#define             nTX_FIFO_ZERO  0x0       
 #define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
-#define              nRX_DAT_ZERO  0x0       
 #define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
-#define               nTX_DAT_RDY  0x0       
 #define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
-#define              nRX_FIFO_RDY  0x0       
 
 /* Bit masks for SDH_STATUS_CLR */
 
 #define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
-#define        nCMD_CRC_FAIL_STAT  0x0       
 #define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
-#define        nDAT_CRC_FAIL_STAT  0x0       
 #define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
-#define         nCMD_TIMEOUT_STAT  0x0       
 #define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
-#define         nDAT_TIMEOUT_STAT  0x0       
 #define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
-#define         nTX_UNDERRUN_STAT  0x0       
 #define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
-#define          nRX_OVERRUN_STAT  0x0       
 #define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
-#define        nCMD_RESP_END_STAT  0x0       
 #define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
-#define            nCMD_SENT_STAT  0x0       
 #define              DAT_END_STAT  0x100      /* Data End Status */
-#define             nDAT_END_STAT  0x0       
 #define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
-#define       nSTART_BIT_ERR_STAT  0x0       
 #define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
-#define         nDAT_BLK_END_STAT  0x0       
 
 /* Bit masks for SDH_MASK0 */
 
 #define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
-#define        nCMD_CRC_FAIL_MASK  0x0       
 #define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
-#define        nDAT_CRC_FAIL_MASK  0x0       
 #define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
-#define         nCMD_TIMEOUT_MASK  0x0       
 #define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
-#define         nDAT_TIMEOUT_MASK  0x0       
 #define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
-#define         nTX_UNDERRUN_MASK  0x0       
 #define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
-#define          nRX_OVERRUN_MASK  0x0       
 #define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
-#define        nCMD_RESP_END_MASK  0x0       
 #define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
-#define            nCMD_SENT_MASK  0x0       
 #define              DAT_END_MASK  0x100      /* Data End Mask */
-#define             nDAT_END_MASK  0x0       
 #define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
-#define       nSTART_BIT_ERR_MASK  0x0       
 #define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
-#define         nDAT_BLK_END_MASK  0x0       
 #define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
-#define             nCMD_ACT_MASK  0x0       
 #define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
-#define              nTX_ACT_MASK  0x0       
 #define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
-#define              nRX_ACT_MASK  0x0       
 #define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
-#define        nTX_FIFO_STAT_MASK  0x0       
 #define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
-#define        nRX_FIFO_STAT_MASK  0x0       
 #define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
-#define        nTX_FIFO_FULL_MASK  0x0       
 #define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
-#define        nRX_FIFO_FULL_MASK  0x0       
 #define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
-#define        nTX_FIFO_ZERO_MASK  0x0       
 #define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
-#define         nRX_DAT_ZERO_MASK  0x0       
 #define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
-#define          nTX_DAT_RDY_MASK  0x0       
 #define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
-#define         nRX_FIFO_RDY_MASK  0x0       
 
 /* Bit masks for SDH_FIFO_CNT */
 
 /* Bit masks for SDH_E_STATUS */
 
 #define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
-#define             nSDIO_INT_DET  0x0       
 #define               SD_CARD_DET  0x10       /* SD Card Detect */
-#define              nSD_CARD_DET  0x0       
 
 /* Bit masks for SDH_E_MASK */
 
 #define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
-#define                 nSDIO_MSK  0x0       
 #define                   SCD_MSK  0x40       /* Mask Card Detect */
-#define                  nSCD_MSK  0x0       
 
 /* Bit masks for SDH_CFG */
 
 #define                   CLKS_EN  0x1        /* Clocks Enable */
-#define                  nCLKS_EN  0x0       
 #define                      SD4E  0x4        /* SDIO 4-Bit Enable */
-#define                     nSD4E  0x0       
 #define                       MWE  0x8        /* Moving Window Enable */
-#define                      nMWE  0x0       
 #define                    SD_RST  0x10       /* SDMMC Reset */
-#define                   nSD_RST  0x0       
 #define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
-#define                nPUP_SDDAT  0x0       
 #define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
-#define               nPUP_SDDAT3  0x0       
 #define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
-#define                nPD_SDDAT3  0x0       
 
 /* Bit masks for SDH_RD_WAIT_EN */
 
 #define                       RWR  0x1        /* Read Wait Request */
-#define                      nRWR  0x0       
 
 /* Bit masks for ATAPI_CONTROL */
 
 #define                 PIO_START  0x1        /* Start PIO/Reg Op */
-#define                nPIO_START  0x0       
 #define               MULTI_START  0x2        /* Start Multi-DMA Op */
-#define              nMULTI_START  0x0       
 #define               ULTRA_START  0x4        /* Start Ultra-DMA Op */
-#define              nULTRA_START  0x0       
 #define                  XFER_DIR  0x8        /* Transfer Direction */
-#define                 nXFER_DIR  0x0       
 #define                  IORDY_EN  0x10       /* IORDY Enable */
-#define                 nIORDY_EN  0x0       
 #define                FIFO_FLUSH  0x20       /* Flush FIFOs */
-#define               nFIFO_FLUSH  0x0       
 #define                  SOFT_RST  0x40       /* Soft Reset */
-#define                 nSOFT_RST  0x0       
 #define                   DEV_RST  0x80       /* Device Reset */
-#define                  nDEV_RST  0x0       
 #define                TFRCNT_RST  0x100      /* Trans Count Reset */
-#define               nTFRCNT_RST  0x0       
 #define               END_ON_TERM  0x200      /* End/Terminate Select */
-#define              nEND_ON_TERM  0x0       
 #define               PIO_USE_DMA  0x400      /* PIO-DMA Enable */
-#define              nPIO_USE_DMA  0x0       
 #define          UDMAIN_FIFO_THRS  0xf000     /* Ultra DMA-IN FIFO Threshold */
 
 /* Bit masks for ATAPI_STATUS */
 
 #define               PIO_XFER_ON  0x1        /* PIO transfer in progress */
-#define              nPIO_XFER_ON  0x0       
 #define             MULTI_XFER_ON  0x2        /* Multi-word DMA transfer in progress */
-#define            nMULTI_XFER_ON  0x0       
 #define             ULTRA_XFER_ON  0x4        /* Ultra DMA transfer in progress */
-#define            nULTRA_XFER_ON  0x0       
 #define               ULTRA_IN_FL  0xf0       /* Ultra DMA Input FIFO Level */
 
 /* Bit masks for ATAPI_DEV_ADDR */
 /* Bit masks for ATAPI_INT_MASK */
 
 #define        ATAPI_DEV_INT_MASK  0x1        /* Device interrupt mask */
-#define       nATAPI_DEV_INT_MASK  0x0       
 #define             PIO_DONE_MASK  0x2        /* PIO transfer done interrupt mask */
-#define            nPIO_DONE_MASK  0x0       
 #define           MULTI_DONE_MASK  0x4        /* Multi-DMA transfer done interrupt mask */
-#define          nMULTI_DONE_MASK  0x0       
 #define          UDMAIN_DONE_MASK  0x8        /* Ultra-DMA in transfer done interrupt mask */
-#define         nUDMAIN_DONE_MASK  0x0       
 #define         UDMAOUT_DONE_MASK  0x10       /* Ultra-DMA out transfer done interrupt mask */
-#define        nUDMAOUT_DONE_MASK  0x0       
 #define       HOST_TERM_XFER_MASK  0x20       /* Host terminate current transfer interrupt mask */
-#define      nHOST_TERM_XFER_MASK  0x0       
 #define           MULTI_TERM_MASK  0x40       /* Device terminate Multi-DMA transfer interrupt mask */
-#define          nMULTI_TERM_MASK  0x0       
 #define          UDMAIN_TERM_MASK  0x80       /* Device terminate Ultra-DMA-in transfer interrupt mask */
-#define         nUDMAIN_TERM_MASK  0x0       
 #define         UDMAOUT_TERM_MASK  0x100      /* Device terminate Ultra-DMA-out transfer interrupt mask */
-#define        nUDMAOUT_TERM_MASK  0x0       
 
 /* Bit masks for ATAPI_INT_STATUS */
 
 #define             ATAPI_DEV_INT  0x1        /* Device interrupt status */
-#define            nATAPI_DEV_INT  0x0       
 #define              PIO_DONE_INT  0x2        /* PIO transfer done interrupt status */
-#define             nPIO_DONE_INT  0x0       
 #define            MULTI_DONE_INT  0x4        /* Multi-DMA transfer done interrupt status */
-#define           nMULTI_DONE_INT  0x0       
 #define           UDMAIN_DONE_INT  0x8        /* Ultra-DMA in transfer done interrupt status */
-#define          nUDMAIN_DONE_INT  0x0       
 #define          UDMAOUT_DONE_INT  0x10       /* Ultra-DMA out transfer done interrupt status */
-#define         nUDMAOUT_DONE_INT  0x0       
 #define        HOST_TERM_XFER_INT  0x20       /* Host terminate current transfer interrupt status */
-#define       nHOST_TERM_XFER_INT  0x0       
 #define            MULTI_TERM_INT  0x40       /* Device terminate Multi-DMA transfer interrupt status */
-#define           nMULTI_TERM_INT  0x0       
 #define           UDMAIN_TERM_INT  0x80       /* Device terminate Ultra-DMA-in transfer interrupt status */
-#define          nUDMAIN_TERM_INT  0x0       
 #define          UDMAOUT_TERM_INT  0x100      /* Device terminate Ultra-DMA-out transfer interrupt status */
-#define         nUDMAOUT_TERM_INT  0x0       
 
 /* Bit masks for ATAPI_LINE_STATUS */
 
 #define                ATAPI_INTR  0x1        /* Device interrupt to host line status */
-#define               nATAPI_INTR  0x0       
 #define                ATAPI_DASP  0x2        /* Device dasp to host line status */
-#define               nATAPI_DASP  0x0       
 #define                ATAPI_CS0N  0x4        /* ATAPI chip select 0 line status */
-#define               nATAPI_CS0N  0x0       
 #define                ATAPI_CS1N  0x8        /* ATAPI chip select 1 line status */
-#define               nATAPI_CS1N  0x0       
 #define                ATAPI_ADDR  0x70       /* ATAPI address line status */
 #define              ATAPI_DMAREQ  0x80       /* ATAPI DMA request line status */
-#define             nATAPI_DMAREQ  0x0       
 #define             ATAPI_DMAACKN  0x100      /* ATAPI DMA acknowledge line status */
-#define            nATAPI_DMAACKN  0x0       
 #define               ATAPI_DIOWN  0x200      /* ATAPI write line status */
-#define              nATAPI_DIOWN  0x0       
 #define               ATAPI_DIORN  0x400      /* ATAPI read line status */
-#define              nATAPI_DIORN  0x0       
 #define               ATAPI_IORDY  0x800      /* ATAPI IORDY line status */
-#define              nATAPI_IORDY  0x0       
 
 /* Bit masks for ATAPI_SM_STATE */
 
 /* Bit masks for ATAPI_TERMINATE */
 
 #define           ATAPI_HOST_TERM  0x1        /* Host terminationation */
-#define          nATAPI_HOST_TERM  0x0       
 
 /* Bit masks for ATAPI_REG_TIM_0 */
 
 /* Bit masks for TIMER_ENABLE1 */
 
 #define                    TIMEN8  0x1        /* Timer 8 Enable */
-#define                   nTIMEN8  0x0       
 #define                    TIMEN9  0x2        /* Timer 9 Enable */
-#define                   nTIMEN9  0x0       
 #define                   TIMEN10  0x4        /* Timer 10 Enable */
-#define                  nTIMEN10  0x0       
 
 /* Bit masks for TIMER_DISABLE1 */
 
 #define                   TIMDIS8  0x1        /* Timer 8 Disable */
-#define                  nTIMDIS8  0x0       
 #define                   TIMDIS9  0x2        /* Timer 9 Disable */
-#define                  nTIMDIS9  0x0       
 #define                  TIMDIS10  0x4        /* Timer 10 Disable */
-#define                 nTIMDIS10  0x0       
 
 /* Bit masks for TIMER_STATUS1 */
 
 #define                    TIMIL8  0x1        /* Timer 8 Interrupt */
-#define                   nTIMIL8  0x0       
 #define                    TIMIL9  0x2        /* Timer 9 Interrupt */
-#define                   nTIMIL9  0x0       
 #define                   TIMIL10  0x4        /* Timer 10 Interrupt */
-#define                  nTIMIL10  0x0       
 #define                 TOVF_ERR8  0x10       /* Timer 8 Counter Overflow */
-#define                nTOVF_ERR8  0x0       
 #define                 TOVF_ERR9  0x20       /* Timer 9 Counter Overflow */
-#define                nTOVF_ERR9  0x0       
 #define                TOVF_ERR10  0x40       /* Timer 10 Counter Overflow */
-#define               nTOVF_ERR10  0x0       
 #define                     TRUN8  0x1000     /* Timer 8 Slave Enable Status */
-#define                    nTRUN8  0x0       
 #define                     TRUN9  0x2000     /* Timer 9 Slave Enable Status */
-#define                    nTRUN9  0x0       
 #define                    TRUN10  0x4000     /* Timer 10 Slave Enable Status */
-#define                   nTRUN10  0x0       
 
 /* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
 
 /* Bit masks for USB_POWER */
 
 #define           ENABLE_SUSPENDM  0x1        /* enable SuspendM output */
-#define          nENABLE_SUSPENDM  0x0       
 #define              SUSPEND_MODE  0x2        /* Suspend Mode indicator */
-#define             nSUSPEND_MODE  0x0       
 #define               RESUME_MODE  0x4        /* DMA Mode */
-#define              nRESUME_MODE  0x0       
 #define                     RESET  0x8        /* Reset indicator */
-#define                    nRESET  0x0       
 #define                   HS_MODE  0x10       /* High Speed mode indicator */
-#define                  nHS_MODE  0x0       
 #define                 HS_ENABLE  0x20       /* high Speed Enable */
-#define                nHS_ENABLE  0x0       
 #define                 SOFT_CONN  0x40       /* Soft connect */
-#define                nSOFT_CONN  0x0       
 #define                ISO_UPDATE  0x80       /* Isochronous update */
-#define               nISO_UPDATE  0x0       
 
 /* Bit masks for USB_INTRTX */
 
 #define                    EP0_TX  0x1        /* Tx Endpoint 0 interrupt */
-#define                   nEP0_TX  0x0       
 #define                    EP1_TX  0x2        /* Tx Endpoint 1 interrupt */
-#define                   nEP1_TX  0x0       
 #define                    EP2_TX  0x4        /* Tx Endpoint 2 interrupt */
-#define                   nEP2_TX  0x0       
 #define                    EP3_TX  0x8        /* Tx Endpoint 3 interrupt */
-#define                   nEP3_TX  0x0       
 #define                    EP4_TX  0x10       /* Tx Endpoint 4 interrupt */
-#define                   nEP4_TX  0x0       
 #define                    EP5_TX  0x20       /* Tx Endpoint 5 interrupt */
-#define                   nEP5_TX  0x0       
 #define                    EP6_TX  0x40       /* Tx Endpoint 6 interrupt */
-#define                   nEP6_TX  0x0       
 #define                    EP7_TX  0x80       /* Tx Endpoint 7 interrupt */
-#define                   nEP7_TX  0x0       
 
 /* Bit masks for USB_INTRRX */
 
 #define                    EP1_RX  0x2        /* Rx Endpoint 1 interrupt */
-#define                   nEP1_RX  0x0       
 #define                    EP2_RX  0x4        /* Rx Endpoint 2 interrupt */
-#define                   nEP2_RX  0x0       
 #define                    EP3_RX  0x8        /* Rx Endpoint 3 interrupt */
-#define                   nEP3_RX  0x0       
 #define                    EP4_RX  0x10       /* Rx Endpoint 4 interrupt */
-#define                   nEP4_RX  0x0       
 #define                    EP5_RX  0x20       /* Rx Endpoint 5 interrupt */
-#define                   nEP5_RX  0x0       
 #define                    EP6_RX  0x40       /* Rx Endpoint 6 interrupt */
-#define                   nEP6_RX  0x0       
 #define                    EP7_RX  0x80       /* Rx Endpoint 7 interrupt */
-#define                   nEP7_RX  0x0       
 
 /* Bit masks for USB_INTRTXE */
 
 #define                  EP0_TX_E  0x1        /* Endpoint 0 interrupt Enable */
-#define                 nEP0_TX_E  0x0       
 #define                  EP1_TX_E  0x2        /* Tx Endpoint 1 interrupt  Enable */
-#define                 nEP1_TX_E  0x0       
 #define                  EP2_TX_E  0x4        /* Tx Endpoint 2 interrupt  Enable */
-#define                 nEP2_TX_E  0x0       
 #define                  EP3_TX_E  0x8        /* Tx Endpoint 3 interrupt  Enable */
-#define                 nEP3_TX_E  0x0       
 #define                  EP4_TX_E  0x10       /* Tx Endpoint 4 interrupt  Enable */
-#define                 nEP4_TX_E  0x0       
 #define                  EP5_TX_E  0x20       /* Tx Endpoint 5 interrupt  Enable */
-#define                 nEP5_TX_E  0x0       
 #define                  EP6_TX_E  0x40       /* Tx Endpoint 6 interrupt  Enable */
-#define                 nEP6_TX_E  0x0       
 #define                  EP7_TX_E  0x80       /* Tx Endpoint 7 interrupt  Enable */
-#define                 nEP7_TX_E  0x0       
 
 /* Bit masks for USB_INTRRXE */
 
 #define                  EP1_RX_E  0x2        /* Rx Endpoint 1 interrupt  Enable */
-#define                 nEP1_RX_E  0x0       
 #define                  EP2_RX_E  0x4        /* Rx Endpoint 2 interrupt  Enable */
-#define                 nEP2_RX_E  0x0       
 #define                  EP3_RX_E  0x8        /* Rx Endpoint 3 interrupt  Enable */
-#define                 nEP3_RX_E  0x0       
 #define                  EP4_RX_E  0x10       /* Rx Endpoint 4 interrupt  Enable */
-#define                 nEP4_RX_E  0x0       
 #define                  EP5_RX_E  0x20       /* Rx Endpoint 5 interrupt  Enable */
-#define                 nEP5_RX_E  0x0       
 #define                  EP6_RX_E  0x40       /* Rx Endpoint 6 interrupt  Enable */
-#define                 nEP6_RX_E  0x0       
 #define                  EP7_RX_E  0x80       /* Rx Endpoint 7 interrupt  Enable */
-#define                 nEP7_RX_E  0x0       
 
 /* Bit masks for USB_INTRUSB */
 
 #define                 SUSPEND_B  0x1        /* Suspend indicator */
-#define                nSUSPEND_B  0x0       
 #define                  RESUME_B  0x2        /* Resume indicator */
-#define                 nRESUME_B  0x0       
 #define          RESET_OR_BABLE_B  0x4        /* Reset/babble indicator */
-#define         nRESET_OR_BABLE_B  0x0       
 #define                     SOF_B  0x8        /* Start of frame */
-#define                    nSOF_B  0x0       
 #define                    CONN_B  0x10       /* Connection indicator */
-#define                   nCONN_B  0x0       
 #define                  DISCON_B  0x20       /* Disconnect indicator */
-#define                 nDISCON_B  0x0       
 #define             SESSION_REQ_B  0x40       /* Session Request */
-#define            nSESSION_REQ_B  0x0       
 #define              VBUS_ERROR_B  0x80       /* Vbus threshold indicator */
-#define             nVBUS_ERROR_B  0x0       
 
 /* Bit masks for USB_INTRUSBE */
 
 #define                SUSPEND_BE  0x1        /* Suspend indicator int enable */
-#define               nSUSPEND_BE  0x0       
 #define                 RESUME_BE  0x2        /* Resume indicator int enable */
-#define                nRESUME_BE  0x0       
 #define         RESET_OR_BABLE_BE  0x4        /* Reset/babble indicator int enable */
-#define        nRESET_OR_BABLE_BE  0x0       
 #define                    SOF_BE  0x8        /* Start of frame int enable */
-#define                   nSOF_BE  0x0       
 #define                   CONN_BE  0x10       /* Connection indicator int enable */
-#define                  nCONN_BE  0x0       
 #define                 DISCON_BE  0x20       /* Disconnect indicator int enable */
-#define                nDISCON_BE  0x0       
 #define            SESSION_REQ_BE  0x40       /* Session Request int enable */
-#define           nSESSION_REQ_BE  0x0       
 #define             VBUS_ERROR_BE  0x80       /* Vbus threshold indicator int enable */
-#define            nVBUS_ERROR_BE  0x0       
 
 /* Bit masks for USB_FRAME */
 
 /* Bit masks for USB_GLOBAL_CTL */
 
 #define                GLOBAL_ENA  0x1        /* enables USB module */
-#define               nGLOBAL_ENA  0x0       
 #define                EP1_TX_ENA  0x2        /* Transmit endpoint 1 enable */
-#define               nEP1_TX_ENA  0x0       
 #define                EP2_TX_ENA  0x4        /* Transmit endpoint 2 enable */
-#define               nEP2_TX_ENA  0x0       
 #define                EP3_TX_ENA  0x8        /* Transmit endpoint 3 enable */
-#define               nEP3_TX_ENA  0x0       
 #define                EP4_TX_ENA  0x10       /* Transmit endpoint 4 enable */
-#define               nEP4_TX_ENA  0x0       
 #define                EP5_TX_ENA  0x20       /* Transmit endpoint 5 enable */
-#define               nEP5_TX_ENA  0x0       
 #define                EP6_TX_ENA  0x40       /* Transmit endpoint 6 enable */
-#define               nEP6_TX_ENA  0x0       
 #define                EP7_TX_ENA  0x80       /* Transmit endpoint 7 enable */
-#define               nEP7_TX_ENA  0x0       
 #define                EP1_RX_ENA  0x100      /* Receive endpoint 1 enable */
-#define               nEP1_RX_ENA  0x0       
 #define                EP2_RX_ENA  0x200      /* Receive endpoint 2 enable */
-#define               nEP2_RX_ENA  0x0       
 #define                EP3_RX_ENA  0x400      /* Receive endpoint 3 enable */
-#define               nEP3_RX_ENA  0x0       
 #define                EP4_RX_ENA  0x800      /* Receive endpoint 4 enable */
-#define               nEP4_RX_ENA  0x0       
 #define                EP5_RX_ENA  0x1000     /* Receive endpoint 5 enable */
-#define               nEP5_RX_ENA  0x0       
 #define                EP6_RX_ENA  0x2000     /* Receive endpoint 6 enable */
-#define               nEP6_RX_ENA  0x0       
 #define                EP7_RX_ENA  0x4000     /* Receive endpoint 7 enable */
-#define               nEP7_RX_ENA  0x0       
 
 /* Bit masks for USB_OTG_DEV_CTL */
 
 #define                   SESSION  0x1        /* session indicator */
-#define                  nSESSION  0x0       
 #define                  HOST_REQ  0x2        /* Host negotiation request */
-#define                 nHOST_REQ  0x0       
 #define                 HOST_MODE  0x4        /* indicates USBDRC is a host */
-#define                nHOST_MODE  0x0       
 #define                     VBUS0  0x8        /* Vbus level indicator[0] */
-#define                    nVBUS0  0x0       
 #define                     VBUS1  0x10       /* Vbus level indicator[1] */
-#define                    nVBUS1  0x0       
 #define                     LSDEV  0x20       /* Low-speed indicator */
-#define                    nLSDEV  0x0       
 #define                     FSDEV  0x40       /* Full or High-speed indicator */
-#define                    nFSDEV  0x0       
 #define                  B_DEVICE  0x80       /* A' or 'B' device indicator */
-#define                 nB_DEVICE  0x0       
 
 /* Bit masks for USB_OTG_VBUS_IRQ */
 
 #define             DRIVE_VBUS_ON  0x1        /* indicator to drive VBUS control circuit */
-#define            nDRIVE_VBUS_ON  0x0       
 #define            DRIVE_VBUS_OFF  0x2        /* indicator to shut off charge pump */
-#define           nDRIVE_VBUS_OFF  0x0       
 #define           CHRG_VBUS_START  0x4        /* indicator for external circuit to start charging VBUS */
-#define          nCHRG_VBUS_START  0x0       
 #define             CHRG_VBUS_END  0x8        /* indicator for external circuit to end charging VBUS */
-#define            nCHRG_VBUS_END  0x0       
 #define        DISCHRG_VBUS_START  0x10       /* indicator to start discharging VBUS */
-#define       nDISCHRG_VBUS_START  0x0       
 #define          DISCHRG_VBUS_END  0x20       /* indicator to stop discharging VBUS */
-#define         nDISCHRG_VBUS_END  0x0       
 
 /* Bit masks for USB_OTG_VBUS_MASK */
 
 #define         DRIVE_VBUS_ON_ENA  0x1        /* enable DRIVE_VBUS_ON interrupt */
-#define        nDRIVE_VBUS_ON_ENA  0x0       
 #define        DRIVE_VBUS_OFF_ENA  0x2        /* enable DRIVE_VBUS_OFF interrupt */
-#define       nDRIVE_VBUS_OFF_ENA  0x0       
 #define       CHRG_VBUS_START_ENA  0x4        /* enable CHRG_VBUS_START interrupt */
-#define      nCHRG_VBUS_START_ENA  0x0       
 #define         CHRG_VBUS_END_ENA  0x8        /* enable CHRG_VBUS_END interrupt */
-#define        nCHRG_VBUS_END_ENA  0x0       
 #define    DISCHRG_VBUS_START_ENA  0x10       /* enable DISCHRG_VBUS_START interrupt */
-#define   nDISCHRG_VBUS_START_ENA  0x0       
 #define      DISCHRG_VBUS_END_ENA  0x20       /* enable DISCHRG_VBUS_END interrupt */
-#define     nDISCHRG_VBUS_END_ENA  0x0       
 
 /* Bit masks for USB_CSR0 */
 
 #define                  RXPKTRDY  0x1        /* data packet receive indicator */
-#define                 nRXPKTRDY  0x0       
 #define                  TXPKTRDY  0x2        /* data packet in FIFO indicator */
-#define                 nTXPKTRDY  0x0       
 #define                STALL_SENT  0x4        /* STALL handshake sent */
-#define               nSTALL_SENT  0x0       
 #define                   DATAEND  0x8        /* Data end indicator */
-#define                  nDATAEND  0x0       
 #define                  SETUPEND  0x10       /* Setup end */
-#define                 nSETUPEND  0x0       
 #define                 SENDSTALL  0x20       /* Send STALL handshake */
-#define                nSENDSTALL  0x0       
 #define         SERVICED_RXPKTRDY  0x40       /* used to clear the RxPktRdy bit */
-#define        nSERVICED_RXPKTRDY  0x0       
 #define         SERVICED_SETUPEND  0x80       /* used to clear the SetupEnd bit */
-#define        nSERVICED_SETUPEND  0x0       
 #define                 FLUSHFIFO  0x100      /* flush endpoint FIFO */
-#define                nFLUSHFIFO  0x0       
 #define          STALL_RECEIVED_H  0x4        /* STALL handshake received host mode */
-#define         nSTALL_RECEIVED_H  0x0       
 #define                SETUPPKT_H  0x8        /* send Setup token host mode */
-#define               nSETUPPKT_H  0x0       
 #define                   ERROR_H  0x10       /* timeout error indicator host mode */
-#define                  nERROR_H  0x0       
 #define                  REQPKT_H  0x20       /* Request an IN transaction host mode */
-#define                 nREQPKT_H  0x0       
 #define               STATUSPKT_H  0x40       /* Status stage transaction host mode */
-#define              nSTATUSPKT_H  0x0       
 #define             NAK_TIMEOUT_H  0x80       /* EP0 halted after a NAK host mode */
-#define            nNAK_TIMEOUT_H  0x0       
 
 /* Bit masks for USB_COUNT0 */
 
 /* Bit masks for USB_TXCSR */
 
 #define                TXPKTRDY_T  0x1        /* data packet in FIFO indicator */
-#define               nTXPKTRDY_T  0x0       
 #define          FIFO_NOT_EMPTY_T  0x2        /* FIFO not empty */
-#define         nFIFO_NOT_EMPTY_T  0x0       
 #define                UNDERRUN_T  0x4        /* TxPktRdy not set  for an IN token */
-#define               nUNDERRUN_T  0x0       
 #define               FLUSHFIFO_T  0x8        /* flush endpoint FIFO */
-#define              nFLUSHFIFO_T  0x0       
 #define              STALL_SEND_T  0x10       /* issue a Stall handshake */
-#define             nSTALL_SEND_T  0x0       
 #define              STALL_SENT_T  0x20       /* Stall handshake transmitted */
-#define             nSTALL_SENT_T  0x0       
 #define        CLEAR_DATATOGGLE_T  0x40       /* clear endpoint data toggle */
-#define       nCLEAR_DATATOGGLE_T  0x0       
 #define                INCOMPTX_T  0x80       /* indicates that a large packet is split */
-#define               nINCOMPTX_T  0x0       
 #define              DMAREQMODE_T  0x400      /* DMA mode (0 or 1) selection */
-#define             nDMAREQMODE_T  0x0       
 #define        FORCE_DATATOGGLE_T  0x800      /* Force data toggle */
-#define       nFORCE_DATATOGGLE_T  0x0       
 #define              DMAREQ_ENA_T  0x1000     /* Enable DMA request for Tx EP */
-#define             nDMAREQ_ENA_T  0x0       
 #define                     ISO_T  0x4000     /* enable Isochronous transfers */
-#define                    nISO_T  0x0       
 #define                 AUTOSET_T  0x8000     /* allows TxPktRdy to be set automatically */
-#define                nAUTOSET_T  0x0       
 #define                  ERROR_TH  0x4        /* error condition host mode */
-#define                 nERROR_TH  0x0       
 #define         STALL_RECEIVED_TH  0x20       /* Stall handshake received host mode */
-#define        nSTALL_RECEIVED_TH  0x0       
 #define            NAK_TIMEOUT_TH  0x80       /* NAK timeout host mode */
-#define           nNAK_TIMEOUT_TH  0x0       
 
 /* Bit masks for USB_TXCOUNT */
 
 /* Bit masks for USB_RXCSR */
 
 #define                RXPKTRDY_R  0x1        /* data packet in FIFO indicator */
-#define               nRXPKTRDY_R  0x0       
 #define               FIFO_FULL_R  0x2        /* FIFO not empty */
-#define              nFIFO_FULL_R  0x0       
 #define                 OVERRUN_R  0x4        /* TxPktRdy not set  for an IN token */
-#define                nOVERRUN_R  0x0       
 #define               DATAERROR_R  0x8        /* Out packet cannot be loaded into Rx  FIFO */
-#define              nDATAERROR_R  0x0       
 #define               FLUSHFIFO_R  0x10       /* flush endpoint FIFO */
-#define              nFLUSHFIFO_R  0x0       
 #define              STALL_SEND_R  0x20       /* issue a Stall handshake */
-#define             nSTALL_SEND_R  0x0       
 #define              STALL_SENT_R  0x40       /* Stall handshake transmitted */
-#define             nSTALL_SENT_R  0x0       
 #define        CLEAR_DATATOGGLE_R  0x80       /* clear endpoint data toggle */
-#define       nCLEAR_DATATOGGLE_R  0x0       
 #define                INCOMPRX_R  0x100      /* indicates that a large packet is split */
-#define               nINCOMPRX_R  0x0       
 #define              DMAREQMODE_R  0x800      /* DMA mode (0 or 1) selection */
-#define             nDMAREQMODE_R  0x0       
 #define                 DISNYET_R  0x1000     /* disable Nyet handshakes */
-#define                nDISNYET_R  0x0       
 #define              DMAREQ_ENA_R  0x2000     /* Enable DMA request for Tx EP */
-#define             nDMAREQ_ENA_R  0x0       
 #define                     ISO_R  0x4000     /* enable Isochronous transfers */
-#define                    nISO_R  0x0       
 #define               AUTOCLEAR_R  0x8000     /* allows TxPktRdy to be set automatically */
-#define              nAUTOCLEAR_R  0x0       
 #define                  ERROR_RH  0x4        /* TxPktRdy not set  for an IN token host mode */
-#define                 nERROR_RH  0x0       
 #define                 REQPKT_RH  0x20       /* request an IN transaction host mode */
-#define                nREQPKT_RH  0x0       
 #define         STALL_RECEIVED_RH  0x40       /* Stall handshake received host mode */
-#define        nSTALL_RECEIVED_RH  0x0       
 #define               INCOMPRX_RH  0x100      /* indicates that a large packet is split host mode */
-#define              nINCOMPRX_RH  0x0       
 #define             DMAREQMODE_RH  0x800      /* DMA mode (0 or 1) selection host mode */
-#define            nDMAREQMODE_RH  0x0       
 #define                AUTOREQ_RH  0x4000     /* sets ReqPkt automatically host mode */
-#define               nAUTOREQ_RH  0x0       
 
 /* Bit masks for USB_RXCOUNT */
 
 /* Bit masks for USB_DMA_INTERRUPT */
 
 #define                  DMA0_INT  0x1        /* DMA0 pending interrupt */
-#define                 nDMA0_INT  0x0       
 #define                  DMA1_INT  0x2        /* DMA1 pending interrupt */
-#define                 nDMA1_INT  0x0       
 #define                  DMA2_INT  0x4        /* DMA2 pending interrupt */
-#define                 nDMA2_INT  0x0       
 #define                  DMA3_INT  0x8        /* DMA3 pending interrupt */
-#define                 nDMA3_INT  0x0       
 #define                  DMA4_INT  0x10       /* DMA4 pending interrupt */
-#define                 nDMA4_INT  0x0       
 #define                  DMA5_INT  0x20       /* DMA5 pending interrupt */
-#define                 nDMA5_INT  0x0       
 #define                  DMA6_INT  0x40       /* DMA6 pending interrupt */
-#define                 nDMA6_INT  0x0       
 #define                  DMA7_INT  0x80       /* DMA7 pending interrupt */
-#define                 nDMA7_INT  0x0       
 
 /* Bit masks for USB_DMAxCONTROL */
 
 #define                   DMA_ENA  0x1        /* DMA enable */
-#define                  nDMA_ENA  0x0       
 #define                 DIRECTION  0x2        /* direction of DMA transfer */
-#define                nDIRECTION  0x0       
 #define                      MODE  0x4        /* DMA Bus error */
-#define                     nMODE  0x0       
 #define                   INT_ENA  0x8        /* Interrupt enable */
-#define                  nINT_ENA  0x0       
 #define                     EPNUM  0xf0       /* EP number */
 #define                  BUSERROR  0x100      /* DMA Bus error */
-#define                 nBUSERROR  0x0       
 
 /* Bit masks for USB_DMAxADDRHIGH */
 
 /* Bit masks for HMDMAx_CONTROL */
 
 #define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
-#define                  nHMDMAEN  0x0       
 #define                       REP  0x2        /* Handshake MDMA Request Polarity */
-#define                      nREP  0x0       
 #define                       UTE  0x8        /* Urgency Threshold Enable */
-#define                      nUTE  0x0       
 #define                       OIE  0x10       /* Overflow Interrupt Enable */
-#define                      nOIE  0x0       
 #define                      BDIE  0x20       /* Block Done Interrupt Enable */
-#define                     nBDIE  0x0       
 #define                      MBDI  0x40       /* Mask Block Done Interrupt */
-#define                     nMBDI  0x0       
 #define                       DRQ  0x300      /* Handshake MDMA Request Type */
 #define                       RBC  0x1000     /* Force Reload of BCOUNT */
-#define                      nRBC  0x0       
 #define                        PS  0x2000     /* Pin Status */
-#define                       nPS  0x0       
 #define                        OI  0x4000     /* Overflow Interrupt Generated */
-#define                       nOI  0x0       
 #define                       BDI  0x8000     /* Block Done Interrupt Generated */
-#define                      nBDI  0x0       
 
 /* ******************************************* */
 /*     MULTI BIT MACRO ENUMERATIONS            */
index a1b200fe6a1f4fe8b455f6fb1ffe798c5cd0399d..895ddd40a838cce33bc295a79e68aea339aa6ab9 100644 (file)
@@ -46,7 +46,7 @@
 
 /* Debug/MP/Emulation Registers (0xFFC00014 - 0xFFC00014) */
 
-#define                           CHIPID  0xffc00014   
+#define                           CHIPID  0xffc00014
 
 /* System Reset and Interrupt Controller (0xFFC00100 - 0xFFC00104) */
 
 /*     and MULTI BIT READ MACROS                              */
 /* ********************************************************** */
 
+/* SIC_IMASK Masks */
+#define SIC_UNMASK_ALL         0x00000000      /* Unmask all peripheral interrupts */
+#define SIC_MASK_ALL           0xFFFFFFFF      /* Mask all peripheral interrupts */
+#define SIC_MASK(x)           (1 << (x))       /* Mask Peripheral #x interrupt */
+#define SIC_UNMASK(x) (0xFFFFFFFF ^ (1 << (x)))        /* Unmask Peripheral #x interrupt */
+
+/* SIC_IWR Masks */
+#define IWR_DISABLE_ALL        0x00000000      /* Wakeup Disable all peripherals */
+#define IWR_ENABLE_ALL         0xFFFFFFFF      /* Wakeup Enable all peripherals */
+#define IWR_ENABLE(x)         (1 << (x))       /* Wakeup Enable Peripheral #x */
+#define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << (x)))       /* Wakeup Disable Peripheral #x */
+
 /* Bit masks for SIC_IAR0 */
 
-#define            IRQ_PLL_WAKEUP  0x1        /* PLL Wakeup */
-#define           nIRQ_PLL_WAKEUP  0x0       
+#define            PLL_WAKEUP  0x1        /* PLL Wakeup */
 
 /* Bit masks for SIC_IWR0, SIC_IMASK0, SIC_ISR0 */
 
-#define              IRQ_DMA0_ERR  0x2        /* DMA Controller 0 Error */
-#define             nIRQ_DMA0_ERR  0x0       
-#define             IRQ_EPPI0_ERR  0x4        /* EPPI0 Error */
-#define            nIRQ_EPPI0_ERR  0x0       
-#define            IRQ_SPORT0_ERR  0x8        /* SPORT0 Error */
-#define           nIRQ_SPORT0_ERR  0x0       
-#define            IRQ_SPORT1_ERR  0x10       /* SPORT1 Error */
-#define           nIRQ_SPORT1_ERR  0x0       
-#define              IRQ_SPI0_ERR  0x20       /* SPI0 Error */
-#define             nIRQ_SPI0_ERR  0x0       
-#define             IRQ_UART0_ERR  0x40       /* UART0 Error */
-#define            nIRQ_UART0_ERR  0x0       
-#define                   IRQ_RTC  0x80       /* Real-Time Clock */
-#define                  nIRQ_RTC  0x0       
-#define                 IRQ_DMA12  0x100      /* DMA Channel 12 */
-#define                nIRQ_DMA12  0x0       
-#define                  IRQ_DMA0  0x200      /* DMA Channel 0 */
-#define                 nIRQ_DMA0  0x0       
-#define                  IRQ_DMA1  0x400      /* DMA Channel 1 */
-#define                 nIRQ_DMA1  0x0       
-#define                  IRQ_DMA2  0x800      /* DMA Channel 2 */
-#define                 nIRQ_DMA2  0x0       
-#define                  IRQ_DMA3  0x1000     /* DMA Channel 3 */
-#define                 nIRQ_DMA3  0x0       
-#define                  IRQ_DMA4  0x2000     /* DMA Channel 4 */
-#define                 nIRQ_DMA4  0x0       
-#define                  IRQ_DMA6  0x4000     /* DMA Channel 6 */
-#define                 nIRQ_DMA6  0x0       
-#define                  IRQ_DMA7  0x8000     /* DMA Channel 7 */
-#define                 nIRQ_DMA7  0x0       
-#define                 IRQ_PINT0  0x80000    /* Pin Interrupt 0 */
-#define                nIRQ_PINT0  0x0       
-#define                 IRQ_PINT1  0x100000   /* Pin Interrupt 1 */
-#define                nIRQ_PINT1  0x0       
-#define                 IRQ_MDMA0  0x200000   /* Memory DMA Stream 0 */
-#define                nIRQ_MDMA0  0x0       
-#define                 IRQ_MDMA1  0x400000   /* Memory DMA Stream 1 */
-#define                nIRQ_MDMA1  0x0       
-#define                  IRQ_WDOG  0x800000   /* Watchdog Timer */
-#define                 nIRQ_WDOG  0x0       
-#define              IRQ_DMA1_ERR  0x1000000  /* DMA Controller 1 Error */
-#define             nIRQ_DMA1_ERR  0x0       
-#define            IRQ_SPORT2_ERR  0x2000000  /* SPORT2 Error */
-#define           nIRQ_SPORT2_ERR  0x0       
-#define            IRQ_SPORT3_ERR  0x4000000  /* SPORT3 Error */
-#define           nIRQ_SPORT3_ERR  0x0       
-#define               IRQ_MXVR_SD  0x8000000  /* MXVR Synchronous Data */
-#define              nIRQ_MXVR_SD  0x0       
-#define              IRQ_SPI1_ERR  0x10000000 /* SPI1 Error */
-#define             nIRQ_SPI1_ERR  0x0       
-#define              IRQ_SPI2_ERR  0x20000000 /* SPI2 Error */
-#define             nIRQ_SPI2_ERR  0x0       
-#define             IRQ_UART1_ERR  0x40000000 /* UART1 Error */
-#define            nIRQ_UART1_ERR  0x0       
-#define             IRQ_UART2_ERR  0x80000000 /* UART2 Error */
-#define            nIRQ_UART2_ERR  0x0       
+#define              DMA0_ERR  0x2        /* DMA Controller 0 Error */
+#define             EPPI0_ERR  0x4        /* EPPI0 Error */
+#define            SPORT0_ERR  0x8        /* SPORT0 Error */
+#define            SPORT1_ERR  0x10       /* SPORT1 Error */
+#define              SPI0_ERR  0x20       /* SPI0 Error */
+#define             UART0_ERR  0x40       /* UART0 Error */
+#define                   RTC  0x80       /* Real-Time Clock */
+#define                 DMA12  0x100      /* DMA Channel 12 */
+#define                  DMA0  0x200      /* DMA Channel 0 */
+#define                  DMA1  0x400      /* DMA Channel 1 */
+#define                  DMA2  0x800      /* DMA Channel 2 */
+#define                  DMA3  0x1000     /* DMA Channel 3 */
+#define                  DMA4  0x2000     /* DMA Channel 4 */
+#define                  DMA6  0x4000     /* DMA Channel 6 */
+#define                  DMA7  0x8000     /* DMA Channel 7 */
+#define                 PINT0  0x80000    /* Pin Interrupt 0 */
+#define                 PINT1  0x100000   /* Pin Interrupt 1 */
+#define                 MDMA0  0x200000   /* Memory DMA Stream 0 */
+#define                 MDMA1  0x400000   /* Memory DMA Stream 1 */
+#define                  WDOG  0x800000   /* Watchdog Timer */
+#define              DMA1_ERR  0x1000000  /* DMA Controller 1 Error */
+#define            SPORT2_ERR  0x2000000  /* SPORT2 Error */
+#define            SPORT3_ERR  0x4000000  /* SPORT3 Error */
+#define               MXVR_SD  0x8000000  /* MXVR Synchronous Data */
+#define              SPI1_ERR  0x10000000 /* SPI1 Error */
+#define              SPI2_ERR  0x20000000 /* SPI2 Error */
+#define             UART1_ERR  0x40000000 /* UART1 Error */
+#define             UART2_ERR  0x80000000 /* UART2 Error */
 
 /* Bit masks for SIC_IWR1, SIC_IMASK1, SIC_ISR1 */
 
-#define              IRQ_CAN0_ERR  0x1        /* CAN0 Error */
-#define             nIRQ_CAN0_ERR  0x0       
-#define                 IRQ_DMA18  0x2        /* DMA Channel 18 */
-#define                nIRQ_DMA18  0x0       
-#define                 IRQ_DMA19  0x4        /* DMA Channel 19 */
-#define                nIRQ_DMA19  0x0       
-#define                 IRQ_DMA20  0x8        /* DMA Channel 20 */
-#define                nIRQ_DMA20  0x0       
-#define                 IRQ_DMA21  0x10       /* DMA Channel 21 */
-#define                nIRQ_DMA21  0x0       
-#define                 IRQ_DMA13  0x20       /* DMA Channel 13 */
-#define                nIRQ_DMA13  0x0       
-#define                 IRQ_DMA14  0x40       /* DMA Channel 14 */
-#define                nIRQ_DMA14  0x0       
-#define                  IRQ_DMA5  0x80       /* DMA Channel 5 */
-#define                 nIRQ_DMA5  0x0       
-#define                 IRQ_DMA23  0x100      /* DMA Channel 23 */
-#define                nIRQ_DMA23  0x0       
-#define                  IRQ_DMA8  0x200      /* DMA Channel 8 */
-#define                 nIRQ_DMA8  0x0       
-#define                  IRQ_DMA9  0x400      /* DMA Channel 9 */
-#define                 nIRQ_DMA9  0x0       
-#define                 IRQ_DMA10  0x800      /* DMA Channel 10 */
-#define                nIRQ_DMA10  0x0       
-#define                 IRQ_DMA11  0x1000     /* DMA Channel 11 */
-#define                nIRQ_DMA11  0x0       
-#define                  IRQ_TWI0  0x2000     /* TWI0 */
-#define                 nIRQ_TWI0  0x0       
-#define                  IRQ_TWI1  0x4000     /* TWI1 */
-#define                 nIRQ_TWI1  0x0       
-#define               IRQ_CAN0_RX  0x8000     /* CAN0 Receive */
-#define              nIRQ_CAN0_RX  0x0       
-#define               IRQ_CAN0_TX  0x10000    /* CAN0 Transmit */
-#define              nIRQ_CAN0_TX  0x0       
-#define                 IRQ_MDMA2  0x20000    /* Memory DMA Stream 0 */
-#define                nIRQ_MDMA2  0x0       
-#define                 IRQ_MDMA3  0x40000    /* Memory DMA Stream 1 */
-#define                nIRQ_MDMA3  0x0       
-#define             IRQ_MXVR_STAT  0x80000    /* MXVR Status */
-#define            nIRQ_MXVR_STAT  0x0       
-#define               IRQ_MXVR_CM  0x100000   /* MXVR Control Message */
-#define              nIRQ_MXVR_CM  0x0       
-#define               IRQ_MXVR_AP  0x200000   /* MXVR Asynchronous Packet */
-#define              nIRQ_MXVR_AP  0x0       
-#define             IRQ_EPPI1_ERR  0x400000   /* EPPI1 Error */
-#define            nIRQ_EPPI1_ERR  0x0       
-#define             IRQ_EPPI2_ERR  0x800000   /* EPPI2 Error */
-#define            nIRQ_EPPI2_ERR  0x0       
-#define             IRQ_UART3_ERR  0x1000000  /* UART3 Error */
-#define            nIRQ_UART3_ERR  0x0       
-#define              IRQ_HOST_ERR  0x2000000  /* Host DMA Port Error */
-#define             nIRQ_HOST_ERR  0x0       
-#define               IRQ_USB_ERR  0x4000000  /* USB Error */
-#define              nIRQ_USB_ERR  0x0       
-#define              IRQ_PIXC_ERR  0x8000000  /* Pixel Compositor Error */
-#define             nIRQ_PIXC_ERR  0x0       
-#define               IRQ_NFC_ERR  0x10000000 /* Nand Flash Controller Error */
-#define              nIRQ_NFC_ERR  0x0       
-#define             IRQ_ATAPI_ERR  0x20000000 /* ATAPI Error */
-#define            nIRQ_ATAPI_ERR  0x0       
-#define              IRQ_CAN1_ERR  0x40000000 /* CAN1 Error */
-#define             nIRQ_CAN1_ERR  0x0       
-#define             IRQ_DMAR0_ERR  0x80000000 /* DMAR0 Overflow Error */
-#define            nIRQ_DMAR0_ERR  0x0       
-#define             IRQ_DMAR1_ERR  0x80000000 /* DMAR1 Overflow Error */
-#define            nIRQ_DMAR1_ERR  0x0       
-#define                 IRQ_DMAR0  0x80000000 /* DMAR0 Block */
-#define                nIRQ_DMAR0  0x0       
-#define                 IRQ_DMAR1  0x80000000 /* DMAR1 Block */
-#define                nIRQ_DMAR1  0x0       
+#define              CAN0_ERR  0x1        /* CAN0 Error */
+#define                 DMA18  0x2        /* DMA Channel 18 */
+#define                 DMA19  0x4        /* DMA Channel 19 */
+#define                 DMA20  0x8        /* DMA Channel 20 */
+#define                 DMA21  0x10       /* DMA Channel 21 */
+#define                 DMA13  0x20       /* DMA Channel 13 */
+#define                 DMA14  0x40       /* DMA Channel 14 */
+#define                  DMA5  0x80       /* DMA Channel 5 */
+#define                 DMA23  0x100      /* DMA Channel 23 */
+#define                  DMA8  0x200      /* DMA Channel 8 */
+#define                  DMA9  0x400      /* DMA Channel 9 */
+#define                 DMA10  0x800      /* DMA Channel 10 */
+#define                 DMA11  0x1000     /* DMA Channel 11 */
+#define                  TWI0  0x2000     /* TWI0 */
+#define                  TWI1  0x4000     /* TWI1 */
+#define               CAN0_RX  0x8000     /* CAN0 Receive */
+#define               CAN0_TX  0x10000    /* CAN0 Transmit */
+#define                 MDMA2  0x20000    /* Memory DMA Stream 0 */
+#define                 MDMA3  0x40000    /* Memory DMA Stream 1 */
+#define             MXVR_STAT  0x80000    /* MXVR Status */
+#define               MXVR_CM  0x100000   /* MXVR Control Message */
+#define               MXVR_AP  0x200000   /* MXVR Asynchronous Packet */
+#define             EPPI1_ERR  0x400000   /* EPPI1 Error */
+#define             EPPI2_ERR  0x800000   /* EPPI2 Error */
+#define             UART3_ERR  0x1000000  /* UART3 Error */
+#define              HOST_ERR  0x2000000  /* Host DMA Port Error */
+#define               USB_ERR  0x4000000  /* USB Error */
+#define              PIXC_ERR  0x8000000  /* Pixel Compositor Error */
+#define               NFC_ERR  0x10000000 /* Nand Flash Controller Error */
+#define             ATAPI_ERR  0x20000000 /* ATAPI Error */
+#define              CAN1_ERR  0x40000000 /* CAN1 Error */
+#define             DMAR0_ERR  0x80000000 /* DMAR0 Overflow Error */
+#define             DMAR1_ERR  0x80000000 /* DMAR1 Overflow Error */
+#define                 DMAR0  0x80000000 /* DMAR0 Block */
+#define                 DMAR1  0x80000000 /* DMAR1 Block */
 
 /* Bit masks for SIC_IWR2, SIC_IMASK2, SIC_ISR2 */
 
-#define                 IRQ_DMA15  0x1        /* DMA Channel 15 */
-#define                nIRQ_DMA15  0x0       
-#define                 IRQ_DMA16  0x2        /* DMA Channel 16 */
-#define                nIRQ_DMA16  0x0       
-#define                 IRQ_DMA17  0x4        /* DMA Channel 17 */
-#define                nIRQ_DMA17  0x0       
-#define                 IRQ_DMA22  0x8        /* DMA Channel 22 */
-#define                nIRQ_DMA22  0x0       
-#define                   IRQ_CNT  0x10       /* Counter */
-#define                  nIRQ_CNT  0x0       
-#define                   IRQ_KEY  0x20       /* Keypad */
-#define                  nIRQ_KEY  0x0       
-#define               IRQ_CAN1_RX  0x40       /* CAN1 Receive */
-#define              nIRQ_CAN1_RX  0x0       
-#define               IRQ_CAN1_TX  0x80       /* CAN1 Transmit */
-#define              nIRQ_CAN1_TX  0x0       
-#define             IRQ_SDH_MASK0  0x100      /* SDH Mask 0 */
-#define            nIRQ_SDH_MASK0  0x0       
-#define             IRQ_SDH_MASK1  0x200      /* SDH Mask 1 */
-#define            nIRQ_SDH_MASK1  0x0       
-#define              IRQ_USB_EINT  0x400      /* USB Exception */
-#define             nIRQ_USB_EINT  0x0       
-#define              IRQ_USB_INT0  0x800      /* USB Interrupt 0 */
-#define             nIRQ_USB_INT0  0x0       
-#define              IRQ_USB_INT1  0x1000     /* USB Interrupt 1 */
-#define             nIRQ_USB_INT1  0x0       
-#define              IRQ_USB_INT2  0x2000     /* USB Interrupt 2 */
-#define             nIRQ_USB_INT2  0x0       
-#define            IRQ_USB_DMAINT  0x4000     /* USB DMA */
-#define           nIRQ_USB_DMAINT  0x0       
-#define                IRQ_OTPSEC  0x8000     /* OTP Access Complete */
-#define               nIRQ_OTPSEC  0x0       
-#define                IRQ_TIMER0  0x400000   /* Timer 0 */
-#define               nIRQ_TIMER0  0x0       
-#define                IRQ_TIMER1  0x800000   /* Timer 1 */
-#define               nIRQ_TIMER1  0x0       
-#define                IRQ_TIMER2  0x1000000  /* Timer 2 */
-#define               nIRQ_TIMER2  0x0       
-#define                IRQ_TIMER3  0x2000000  /* Timer 3 */
-#define               nIRQ_TIMER3  0x0       
-#define                IRQ_TIMER4  0x4000000  /* Timer 4 */
-#define               nIRQ_TIMER4  0x0       
-#define                IRQ_TIMER5  0x8000000  /* Timer 5 */
-#define               nIRQ_TIMER5  0x0       
-#define                IRQ_TIMER6  0x10000000 /* Timer 6 */
-#define               nIRQ_TIMER6  0x0       
-#define                IRQ_TIMER7  0x20000000 /* Timer 7 */
-#define               nIRQ_TIMER7  0x0       
-#define                 IRQ_PINT2  0x40000000 /* Pin Interrupt 2 */
-#define                nIRQ_PINT2  0x0       
-#define                 IRQ_PINT3  0x80000000 /* Pin Interrupt 3 */
-#define                nIRQ_PINT3  0x0       
+#define                 DMA15  0x1        /* DMA Channel 15 */
+#define                 DMA16  0x2        /* DMA Channel 16 */
+#define                 DMA17  0x4        /* DMA Channel 17 */
+#define                 DMA22  0x8        /* DMA Channel 22 */
+#define                   CNT  0x10       /* Counter */
+#define                   KEY  0x20       /* Keypad */
+#define               CAN1_RX  0x40       /* CAN1 Receive */
+#define               CAN1_TX  0x80       /* CAN1 Transmit */
+#define             SDH_INT_MASK0  0x100      /* SDH Mask 0 */
+#define             SDH_INT_MASK1  0x200      /* SDH Mask 1 */
+#define              USB_EINT  0x400      /* USB Exception */
+#define              USB_INT0  0x800      /* USB Interrupt 0 */
+#define              USB_INT1  0x1000     /* USB Interrupt 1 */
+#define              USB_INT2  0x2000     /* USB Interrupt 2 */
+#define            USB_DMAINT  0x4000     /* USB DMA */
+#define                OTPSEC  0x8000     /* OTP Access Complete */
+#define                TIMER0  0x400000   /* Timer 0 */
+#define                TIMER1  0x800000   /* Timer 1 */
+#define                TIMER2  0x1000000  /* Timer 2 */
+#define                TIMER3  0x2000000  /* Timer 3 */
+#define                TIMER4  0x4000000  /* Timer 4 */
+#define                TIMER5  0x8000000  /* Timer 5 */
+#define                TIMER6  0x10000000 /* Timer 6 */
+#define                TIMER7  0x20000000 /* Timer 7 */
+#define                 PINT2  0x40000000 /* Pin Interrupt 2 */
+#define                 PINT3  0x80000000 /* Pin Interrupt 3 */
 
 /* Bit masks for DMAx_CONFIG, MDMA_Sx_CONFIG, MDMA_Dx_CONFIG */
 
 #define                     DMAEN  0x1        /* DMA Channel Enable */
-#define                    nDMAEN  0x0       
 #define                       WNR  0x2        /* DMA Direction */
-#define                      nWNR  0x0       
-#define                    WDSIZE  0xc        /* Transfer Word Size */
+#define                  WDSIZE_8  0x0        /* Transfer Word Size = 8 */
+#define                 WDSIZE_16  0x4        /* Transfer Word Size = 16 */
+#define                 WDSIZE_32  0x8        /* Transfer Word Size = 32 */
 #define                     DMA2D  0x10       /* DMA Mode */
-#define                    nDMA2D  0x0       
 #define                   RESTART  0x20       /* Work Unit Transitions */
-#define                  nRESTART  0x0       
 #define                    DI_SEL  0x40       /* Data Interrupt Timing Select */
-#define                   nDI_SEL  0x0       
 #define                     DI_EN  0x80       /* Data Interrupt Enable */
-#define                    nDI_EN  0x0       
 #define                    NDSIZE  0xf00      /* Flex Descriptor Size */
 #define                   DMAFLOW  0xf000     /* Next Operation */
 
 /* Bit masks for DMAx_IRQ_STATUS, MDMA_Sx_IRQ_STATUS, MDMA_Dx_IRQ_STATUS */
 
 #define                  DMA_DONE  0x1        /* DMA Completion Interrupt Status */
-#define                 nDMA_DONE  0x0       
 #define                   DMA_ERR  0x2        /* DMA Error Interrupt Status */
-#define                  nDMA_ERR  0x0       
 #define                    DFETCH  0x4        /* DMA Descriptor Fetch */
-#define                   nDFETCH  0x0       
 #define                   DMA_RUN  0x8        /* DMA Channel Running */
-#define                  nDMA_RUN  0x0       
 
 /* Bit masks for DMAx_PERIPHERAL_MAP, MDMA_Sx_IRQ_STATUS, MDMA_Dx_IRQ_STATUS */
 
 #define                     CTYPE  0x40       /* DMA Channel Type */
-#define                    nCTYPE  0x0       
 #define                      PMAP  0xf000     /* Peripheral Mapped To This Channel */
 
 /* Bit masks for DMACx_TCPER */
 /* Bit masks for DMAC1_PERIMUX */
 
 #define                   PMUXSDH  0x1        /* Peripheral Select for DMA22 channel */
-#define                  nPMUXSDH  0x0       
 
-/* Bit masks for EBIU_AMGCTL */
+/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
+/* EBIU_AMGCTL Masks                                                                                                                                   */
+#define AMCKEN                 0x0001          /* Enable CLKOUT                                                                        */
+#define        AMBEN_NONE              0x0000          /* All Banks Disabled                                                           */
+#define AMBEN_B0               0x0002          /* Enable Async Memory Bank 0 only                                      */
+#define AMBEN_B0_B1            0x0004          /* Enable Async Memory Banks 0 & 1 only                         */
+#define AMBEN_B0_B1_B2 0x0006          /* Enable Async Memory Banks 0, 1, and 2                        */
+#define AMBEN_ALL              0x0008          /* Enable Async Memory Banks (all) 0, 1, 2, and 3       */
 
-#define                    AMCKEN  0x1        /* Async Memory Enable */
-#define                   nAMCKEN  0x0       
-#define                     AMBEN  0xe        /* Async bank enable */
 
 /* Bit masks for EBIU_AMBCTL0 */
 
 #define                   B0RDYEN  0x1        /* Bank 0 ARDY Enable */
-#define                  nB0RDYEN  0x0       
 #define                  B0RDYPOL  0x2        /* Bank 0 ARDY Polarity */
-#define                 nB0RDYPOL  0x0       
 #define                      B0TT  0xc        /* Bank 0 transition time */
 #define                      B0ST  0x30       /* Bank 0 Setup time */
 #define                      B0HT  0xc0       /* Bank 0 Hold time */
 #define                     B0RAT  0xf00      /* Bank 0 Read access time */
 #define                     B0WAT  0xf000     /* Bank 0 write access time */
 #define                   B1RDYEN  0x10000    /* Bank 1 ARDY Enable */
-#define                  nB1RDYEN  0x0       
 #define                  B1RDYPOL  0x20000    /* Bank 1 ARDY Polarity */
-#define                 nB1RDYPOL  0x0       
 #define                      B1TT  0xc0000    /* Bank 1 transition time */
 #define                      B1ST  0x300000   /* Bank 1 Setup time */
 #define                      B1HT  0xc00000   /* Bank 1 Hold time */
 /* Bit masks for EBIU_AMBCTL1 */
 
 #define                   B2RDYEN  0x1        /* Bank 2 ARDY Enable */
-#define                  nB2RDYEN  0x0       
 #define                  B2RDYPOL  0x2        /* Bank 2 ARDY Polarity */
-#define                 nB2RDYPOL  0x0       
 #define                      B2TT  0xc        /* Bank 2 transition time */
 #define                      B2ST  0x30       /* Bank 2 Setup time */
 #define                      B2HT  0xc0       /* Bank 2 Hold time */
 #define                     B2RAT  0xf00      /* Bank 2 Read access time */
 #define                     B2WAT  0xf000     /* Bank 2 write access time */
 #define                   B3RDYEN  0x10000    /* Bank 3 ARDY Enable */
-#define                  nB3RDYEN  0x0       
 #define                  B3RDYPOL  0x20000    /* Bank 3 ARDY Polarity */
-#define                 nB3RDYPOL  0x0       
 #define                      B3TT  0xc0000    /* Bank 3 transition time */
 #define                      B3ST  0x300000   /* Bank 3 Setup time */
 #define                      B3HT  0xc00000   /* Bank 3 Hold time */
 /* Bit masks for EBIU_FCTL */
 
 #define               TESTSETLOCK  0x1        /* Test set lock */
-#define              nTESTSETLOCK  0x0       
 #define                      BCLK  0x6        /* Burst clock frequency */
 #define                      PGWS  0x38       /* Page wait states */
 #define                      PGSZ  0x40       /* Page size */
-#define                     nPGSZ  0x0       
 #define                      RDDL  0x380      /* Read data delay */
 
 /* Bit masks for EBIU_ARBSTAT */
 
 #define                   ARBSTAT  0x1        /* Arbitration status */
-#define                  nARBSTAT  0x0       
 #define                    BGSTAT  0x2        /* Bus grant status */
-#define                   nBGSTAT  0x0       
 
 /* Bit masks for EBIU_DDRCTL0 */
 
 #define               BURSTLENGTH  0x7        /* Burst length */
 #define                CASLATENCY  0x70       /* CAS latency */
 #define                  DLLRESET  0x100      /* DLL Reset */
-#define                 nDLLRESET  0x0       
 #define                      REGE  0x1000     /* Register mode enable */
-#define                     nREGE  0x0       
 
 /* Bit masks for EBIU_DDRCTL3 */
 
 #define                DEB3_PFLEN  0x30       /* Pre fetch length for DEB3 accesses */
 #define          DEB_ARB_PRIORITY  0x700      /* Arbitration between DEB busses */
 #define               DEB1_URGENT  0x1000     /* DEB1 Urgent */
-#define              nDEB1_URGENT  0x0       
 #define               DEB2_URGENT  0x2000     /* DEB2 Urgent */
-#define              nDEB2_URGENT  0x0       
 #define               DEB3_URGENT  0x4000     /* DEB3 Urgent */
-#define              nDEB3_URGENT  0x0       
 
 /* Bit masks for EBIU_ERRMST */
 
 #define                DEB1_ERROR  0x1        /* DEB1 Error */
-#define               nDEB1_ERROR  0x0       
 #define                DEB2_ERROR  0x2        /* DEB2 Error */
-#define               nDEB2_ERROR  0x0       
 #define                DEB3_ERROR  0x4        /* DEB3 Error */
-#define               nDEB3_ERROR  0x0       
 #define                CORE_ERROR  0x8        /* Core error */
-#define               nCORE_ERROR  0x0       
 #define                DEB_MERROR  0x10       /* DEB1 Error (2nd) */
-#define               nDEB_MERROR  0x0       
 #define               DEB2_MERROR  0x20       /* DEB2 Error (2nd) */
-#define              nDEB2_MERROR  0x0       
 #define               DEB3_MERROR  0x40       /* DEB3 Error (2nd) */
-#define              nDEB3_MERROR  0x0       
 #define               CORE_MERROR  0x80       /* Core Error (2nd) */
-#define              nCORE_MERROR  0x0       
 
 /* Bit masks for EBIU_ERRADD */
 
 /* Bit masks for EBIU_RSTCTL */
 
 #define                 DDRSRESET  0x1        /* DDR soft reset */
-#define                nDDRSRESET  0x0       
 #define               PFTCHSRESET  0x4        /* DDR prefetch reset */
-#define              nPFTCHSRESET  0x0       
 #define                     SRREQ  0x8        /* Self-refresh request */
-#define                    nSRREQ  0x0       
 #define                     SRACK  0x10       /* Self-refresh acknowledge */
-#define                    nSRACK  0x0       
 #define                MDDRENABLE  0x20       /* Mobile DDR enable */
-#define               nMDDRENABLE  0x0       
 
 /* Bit masks for EBIU_DDRBRC0 */
 
 /* Bit masks for EBIU_DDRMCEN */
 
 #define                B0WCENABLE  0x1        /* Bank 0 write count enable */
-#define               nB0WCENABLE  0x0       
 #define                B1WCENABLE  0x2        /* Bank 1 write count enable */
-#define               nB1WCENABLE  0x0       
 #define                B2WCENABLE  0x4        /* Bank 2 write count enable */
-#define               nB2WCENABLE  0x0       
 #define                B3WCENABLE  0x8        /* Bank 3 write count enable */
-#define               nB3WCENABLE  0x0       
 #define                B4WCENABLE  0x10       /* Bank 4 write count enable */
-#define               nB4WCENABLE  0x0       
 #define                B5WCENABLE  0x20       /* Bank 5 write count enable */
-#define               nB5WCENABLE  0x0       
 #define                B6WCENABLE  0x40       /* Bank 6 write count enable */
-#define               nB6WCENABLE  0x0       
 #define                B7WCENABLE  0x80       /* Bank 7 write count enable */
-#define               nB7WCENABLE  0x0       
 #define                B0RCENABLE  0x100      /* Bank 0 read count enable */
-#define               nB0RCENABLE  0x0       
 #define                B1RCENABLE  0x200      /* Bank 1 read count enable */
-#define               nB1RCENABLE  0x0       
 #define                B2RCENABLE  0x400      /* Bank 2 read count enable */
-#define               nB2RCENABLE  0x0       
 #define                B3RCENABLE  0x800      /* Bank 3 read count enable */
-#define               nB3RCENABLE  0x0       
 #define                B4RCENABLE  0x1000     /* Bank 4 read count enable */
-#define               nB4RCENABLE  0x0       
 #define                B5RCENABLE  0x2000     /* Bank 5 read count enable */
-#define               nB5RCENABLE  0x0       
 #define                B6RCENABLE  0x4000     /* Bank 6 read count enable */
-#define               nB6RCENABLE  0x0       
 #define                B7RCENABLE  0x8000     /* Bank 7 read count enable */
-#define               nB7RCENABLE  0x0       
 #define             ROWACTCENABLE  0x10000    /* DDR Row activate count enable */
-#define            nROWACTCENABLE  0x0       
 #define                RWTCENABLE  0x20000    /* DDR R/W Turn around count enable */
-#define               nRWTCENABLE  0x0       
 #define                 ARCENABLE  0x40000    /* DDR Auto-refresh count enable */
-#define                nARCENABLE  0x0       
 #define                 GC0ENABLE  0x100000   /* DDR Grant count 0 enable */
-#define                nGC0ENABLE  0x0       
 #define                 GC1ENABLE  0x200000   /* DDR Grant count 1 enable */
-#define                nGC1ENABLE  0x0       
 #define                 GC2ENABLE  0x400000   /* DDR Grant count 2 enable */
-#define                nGC2ENABLE  0x0       
 #define                 GC3ENABLE  0x800000   /* DDR Grant count 3 enable */
-#define                nGC3ENABLE  0x0       
 #define                 GCCONTROL  0x3000000  /* DDR Grant Count Control */
 
 /* Bit masks for EBIU_DDRMCCL */
 
 #define                 CB0WCOUNT  0x1        /* Clear write count 0 */
-#define                nCB0WCOUNT  0x0       
 #define                 CB1WCOUNT  0x2        /* Clear write count 1 */
-#define                nCB1WCOUNT  0x0       
 #define                 CB2WCOUNT  0x4        /* Clear write count 2 */
-#define                nCB2WCOUNT  0x0       
 #define                 CB3WCOUNT  0x8        /* Clear write count 3 */
-#define                nCB3WCOUNT  0x0       
 #define                 CB4WCOUNT  0x10       /* Clear write count 4 */
-#define                nCB4WCOUNT  0x0       
 #define                 CB5WCOUNT  0x20       /* Clear write count 5 */
-#define                nCB5WCOUNT  0x0       
 #define                 CB6WCOUNT  0x40       /* Clear write count 6 */
-#define                nCB6WCOUNT  0x0       
 #define                 CB7WCOUNT  0x80       /* Clear write count 7 */
-#define                nCB7WCOUNT  0x0       
 #define                  CBRCOUNT  0x100      /* Clear read count 0 */
-#define                 nCBRCOUNT  0x0       
 #define                 CB1RCOUNT  0x200      /* Clear read count 1 */
-#define                nCB1RCOUNT  0x0       
 #define                 CB2RCOUNT  0x400      /* Clear read count 2 */
-#define                nCB2RCOUNT  0x0       
 #define                 CB3RCOUNT  0x800      /* Clear read count 3 */
-#define                nCB3RCOUNT  0x0       
 #define                 CB4RCOUNT  0x1000     /* Clear read count 4 */
-#define                nCB4RCOUNT  0x0       
 #define                 CB5RCOUNT  0x2000     /* Clear read count 5 */
-#define                nCB5RCOUNT  0x0       
 #define                 CB6RCOUNT  0x4000     /* Clear read count 6 */
-#define                nCB6RCOUNT  0x0       
 #define                 CB7RCOUNT  0x8000     /* Clear read count 7 */
-#define                nCB7RCOUNT  0x0       
 #define                  CRACOUNT  0x10000    /* Clear row activation count */
-#define                 nCRACOUNT  0x0       
 #define                CRWTACOUNT  0x20000    /* Clear R/W turn-around count */
-#define               nCRWTACOUNT  0x0       
 #define                  CARCOUNT  0x40000    /* Clear auto-refresh count */
-#define                 nCARCOUNT  0x0       
 #define                  CG0COUNT  0x100000   /* Clear grant count 0 */
-#define                 nCG0COUNT  0x0       
 #define                  CG1COUNT  0x200000   /* Clear grant count 1 */
-#define                 nCG1COUNT  0x0       
 #define                  CG2COUNT  0x400000   /* Clear grant count 2 */
-#define                 nCG2COUNT  0x0       
 #define                  CG3COUNT  0x800000   /* Clear grant count 3 */
-#define                 nCG3COUNT  0x0       
 
 /* Bit masks for (PORTx is PORTA - PORTJ) includes PORTx_FER, PORTx_SET, PORTx_CLEAR, PORTx_DIR_SET, PORTx_DIR_CLEAR, PORTx_INEN */
 
 #define                       Px0  0x1        /* GPIO 0 */
-#define                      nPx0  0x0       
 #define                       Px1  0x2        /* GPIO 1 */
-#define                      nPx1  0x0       
 #define                       Px2  0x4        /* GPIO 2 */
-#define                      nPx2  0x0       
 #define                       Px3  0x8        /* GPIO 3 */
-#define                      nPx3  0x0       
 #define                       Px4  0x10       /* GPIO 4 */
-#define                      nPx4  0x0       
 #define                       Px5  0x20       /* GPIO 5 */
-#define                      nPx5  0x0       
 #define                       Px6  0x40       /* GPIO 6 */
-#define                      nPx6  0x0       
 #define                       Px7  0x80       /* GPIO 7 */
-#define                      nPx7  0x0       
 #define                       Px8  0x100      /* GPIO 8 */
-#define                      nPx8  0x0       
 #define                       Px9  0x200      /* GPIO 9 */
-#define                      nPx9  0x0       
 #define                      Px10  0x400      /* GPIO 10 */
-#define                     nPx10  0x0       
 #define                      Px11  0x800      /* GPIO 11 */
-#define                     nPx11  0x0       
 #define                      Px12  0x1000     /* GPIO 12 */
-#define                     nPx12  0x0       
 #define                      Px13  0x2000     /* GPIO 13 */
-#define                     nPx13  0x0       
 #define                      Px14  0x4000     /* GPIO 14 */
-#define                     nPx14  0x0       
 #define                      Px15  0x8000     /* GPIO 15 */
-#define                     nPx15  0x0       
 
 /* Bit masks for PORTA_MUX - PORTJ_MUX */
 
 /* Bit masks for PINTx_MASK_SET/CLEAR, PINTx_REQUEST, PINTx_LATCH, PINTx_EDGE_SET/CLEAR, PINTx_INVERT_SET/CLEAR, PINTx_PINTSTATE */
 
 #define                       IB0  0x1        /* Interrupt Bit 0 */
-#define                      nIB0  0x0       
 #define                       IB1  0x2        /* Interrupt Bit 1 */
-#define                      nIB1  0x0       
 #define                       IB2  0x4        /* Interrupt Bit 2 */
-#define                      nIB2  0x0       
 #define                       IB3  0x8        /* Interrupt Bit 3 */
-#define                      nIB3  0x0       
 #define                       IB4  0x10       /* Interrupt Bit 4 */
-#define                      nIB4  0x0       
 #define                       IB5  0x20       /* Interrupt Bit 5 */
-#define                      nIB5  0x0       
 #define                       IB6  0x40       /* Interrupt Bit 6 */
-#define                      nIB6  0x0       
 #define                       IB7  0x80       /* Interrupt Bit 7 */
-#define                      nIB7  0x0       
 #define                       IB8  0x100      /* Interrupt Bit 8 */
-#define                      nIB8  0x0       
 #define                       IB9  0x200      /* Interrupt Bit 9 */
-#define                      nIB9  0x0       
 #define                      IB10  0x400      /* Interrupt Bit 10 */
-#define                     nIB10  0x0       
 #define                      IB11  0x800      /* Interrupt Bit 11 */
-#define                     nIB11  0x0       
 #define                      IB12  0x1000     /* Interrupt Bit 12 */
-#define                     nIB12  0x0       
 #define                      IB13  0x2000     /* Interrupt Bit 13 */
-#define                     nIB13  0x0       
 #define                      IB14  0x4000     /* Interrupt Bit 14 */
-#define                     nIB14  0x0       
 #define                      IB15  0x8000     /* Interrupt Bit 15 */
-#define                     nIB15  0x0       
 
 /* Bit masks for TIMERx_CONFIG */
 
 #define                     TMODE  0x3        /* Timer Mode */
 #define                  PULSE_HI  0x4        /* Pulse Polarity */
-#define                 nPULSE_HI  0x0       
 #define                PERIOD_CNT  0x8        /* Period Count */
-#define               nPERIOD_CNT  0x0       
 #define                   IRQ_ENA  0x10       /* Interrupt Request Enable */
-#define                  nIRQ_ENA  0x0       
 #define                   TIN_SEL  0x20       /* Timer Input Select */
-#define                  nTIN_SEL  0x0       
 #define                   OUT_DIS  0x40       /* Output Pad Disable */
-#define                  nOUT_DIS  0x0       
 #define                   CLK_SEL  0x80       /* Timer Clock Select */
-#define                  nCLK_SEL  0x0       
 #define                 TOGGLE_HI  0x100      /* Toggle Mode */
-#define                nTOGGLE_HI  0x0       
 #define                   EMU_RUN  0x200      /* Emulation Behavior Select */
-#define                  nEMU_RUN  0x0       
 #define                   ERR_TYP  0xc000     /* Error Type */
 
 /* Bit masks for TIMER_ENABLE0 */
 
 #define                    TIMEN0  0x1        /* Timer 0 Enable */
-#define                   nTIMEN0  0x0       
 #define                    TIMEN1  0x2        /* Timer 1 Enable */
-#define                   nTIMEN1  0x0       
 #define                    TIMEN2  0x4        /* Timer 2 Enable */
-#define                   nTIMEN2  0x0       
 #define                    TIMEN3  0x8        /* Timer 3 Enable */
-#define                   nTIMEN3  0x0       
 #define                    TIMEN4  0x10       /* Timer 4 Enable */
-#define                   nTIMEN4  0x0       
 #define                    TIMEN5  0x20       /* Timer 5 Enable */
-#define                   nTIMEN5  0x0       
 #define                    TIMEN6  0x40       /* Timer 6 Enable */
-#define                   nTIMEN6  0x0       
 #define                    TIMEN7  0x80       /* Timer 7 Enable */
-#define                   nTIMEN7  0x0       
 
 /* Bit masks for TIMER_DISABLE0 */
 
 #define                   TIMDIS0  0x1        /* Timer 0 Disable */
-#define                  nTIMDIS0  0x0       
 #define                   TIMDIS1  0x2        /* Timer 1 Disable */
-#define                  nTIMDIS1  0x0       
 #define                   TIMDIS2  0x4        /* Timer 2 Disable */
-#define                  nTIMDIS2  0x0       
 #define                   TIMDIS3  0x8        /* Timer 3 Disable */
-#define                  nTIMDIS3  0x0       
 #define                   TIMDIS4  0x10       /* Timer 4 Disable */
-#define                  nTIMDIS4  0x0       
 #define                   TIMDIS5  0x20       /* Timer 5 Disable */
-#define                  nTIMDIS5  0x0       
 #define                   TIMDIS6  0x40       /* Timer 6 Disable */
-#define                  nTIMDIS6  0x0       
 #define                   TIMDIS7  0x80       /* Timer 7 Disable */
-#define                  nTIMDIS7  0x0       
 
 /* Bit masks for TIMER_STATUS0 */
 
 #define                    TIMIL0  0x1        /* Timer 0 Interrupt */
-#define                   nTIMIL0  0x0       
 #define                    TIMIL1  0x2        /* Timer 1 Interrupt */
-#define                   nTIMIL1  0x0       
 #define                    TIMIL2  0x4        /* Timer 2 Interrupt */
-#define                   nTIMIL2  0x0       
 #define                    TIMIL3  0x8        /* Timer 3 Interrupt */
-#define                   nTIMIL3  0x0       
 #define                 TOVF_ERR0  0x10       /* Timer 0 Counter Overflow */
-#define                nTOVF_ERR0  0x0       
 #define                 TOVF_ERR1  0x20       /* Timer 1 Counter Overflow */
-#define                nTOVF_ERR1  0x0       
 #define                 TOVF_ERR2  0x40       /* Timer 2 Counter Overflow */
-#define                nTOVF_ERR2  0x0       
 #define                 TOVF_ERR3  0x80       /* Timer 3 Counter Overflow */
-#define                nTOVF_ERR3  0x0       
 #define                     TRUN0  0x1000     /* Timer 0 Slave Enable Status */
-#define                    nTRUN0  0x0       
 #define                     TRUN1  0x2000     /* Timer 1 Slave Enable Status */
-#define                    nTRUN1  0x0       
 #define                     TRUN2  0x4000     /* Timer 2 Slave Enable Status */
-#define                    nTRUN2  0x0       
 #define                     TRUN3  0x8000     /* Timer 3 Slave Enable Status */
-#define                    nTRUN3  0x0       
 #define                    TIMIL4  0x10000    /* Timer 4 Interrupt */
-#define                   nTIMIL4  0x0       
 #define                    TIMIL5  0x20000    /* Timer 5 Interrupt */
-#define                   nTIMIL5  0x0       
 #define                    TIMIL6  0x40000    /* Timer 6 Interrupt */
-#define                   nTIMIL6  0x0       
 #define                    TIMIL7  0x80000    /* Timer 7 Interrupt */
-#define                   nTIMIL7  0x0       
 #define                 TOVF_ERR4  0x100000   /* Timer 4 Counter Overflow */
-#define                nTOVF_ERR4  0x0       
 #define                 TOVF_ERR5  0x200000   /* Timer 5 Counter Overflow */
-#define                nTOVF_ERR5  0x0       
 #define                 TOVF_ERR6  0x400000   /* Timer 6 Counter Overflow */
-#define                nTOVF_ERR6  0x0       
 #define                 TOVF_ERR7  0x800000   /* Timer 7 Counter Overflow */
-#define                nTOVF_ERR7  0x0       
 #define                     TRUN4  0x10000000 /* Timer 4 Slave Enable Status */
-#define                    nTRUN4  0x0       
 #define                     TRUN5  0x20000000 /* Timer 5 Slave Enable Status */
-#define                    nTRUN5  0x0       
 #define                     TRUN6  0x40000000 /* Timer 6 Slave Enable Status */
-#define                    nTRUN6  0x0       
 #define                     TRUN7  0x80000000 /* Timer 7 Slave Enable Status */
-#define                    nTRUN7  0x0       
 
 /* Bit masks for WDOG_CTL */
 
 #define                      WDEV  0x6        /* Watchdog Event */
 #define                      WDEN  0xff0      /* Watchdog Enable */
 #define                      WDRO  0x8000     /* Watchdog Rolled Over */
-#define                     nWDRO  0x0       
 
 /* Bit masks for CNT_CONFIG */
 
 #define                      CNTE  0x1        /* Counter Enable */
-#define                     nCNTE  0x0       
 #define                      DEBE  0x2        /* Debounce Enable */
-#define                     nDEBE  0x0       
 #define                    CDGINV  0x10       /* CDG Pin Polarity Invert */
-#define                   nCDGINV  0x0       
 #define                    CUDINV  0x20       /* CUD Pin Polarity Invert */
-#define                   nCUDINV  0x0       
 #define                    CZMINV  0x40       /* CZM Pin Polarity Invert */
-#define                   nCZMINV  0x0       
 #define                   CNTMODE  0x700      /* Counter Operating Mode */
 #define                      ZMZC  0x800      /* CZM Zeroes Counter Enable */
-#define                     nZMZC  0x0       
 #define                   BNDMODE  0x3000     /* Boundary register Mode */
 #define                    INPDIS  0x8000     /* CUG and CDG Input Disable */
-#define                   nINPDIS  0x0       
 
 /* Bit masks for CNT_IMASK */
 
 #define                      ICIE  0x1        /* Illegal Gray/Binary Code Interrupt Enable */
-#define                     nICIE  0x0       
 #define                      UCIE  0x2        /* Up count Interrupt Enable */
-#define                     nUCIE  0x0       
 #define                      DCIE  0x4        /* Down count Interrupt Enable */
-#define                     nDCIE  0x0       
 #define                    MINCIE  0x8        /* Min Count Interrupt Enable */
-#define                   nMINCIE  0x0       
 #define                    MAXCIE  0x10       /* Max Count Interrupt Enable */
-#define                   nMAXCIE  0x0       
 #define                   COV31IE  0x20       /* Bit 31 Overflow Interrupt Enable */
-#define                  nCOV31IE  0x0       
 #define                   COV15IE  0x40       /* Bit 15 Overflow Interrupt Enable */
-#define                  nCOV15IE  0x0       
 #define                   CZEROIE  0x80       /* Count to Zero Interrupt Enable */
-#define                  nCZEROIE  0x0       
 #define                     CZMIE  0x100      /* CZM Pin Interrupt Enable */
-#define                    nCZMIE  0x0       
 #define                    CZMEIE  0x200      /* CZM Error Interrupt Enable */
-#define                   nCZMEIE  0x0       
 #define                    CZMZIE  0x400      /* CZM Zeroes Counter Interrupt Enable */
-#define                   nCZMZIE  0x0       
 
 /* Bit masks for CNT_STATUS */
 
 #define                      ICII  0x1        /* Illegal Gray/Binary Code Interrupt Identifier */
-#define                     nICII  0x0       
 #define                      UCII  0x2        /* Up count Interrupt Identifier */
-#define                     nUCII  0x0       
 #define                      DCII  0x4        /* Down count Interrupt Identifier */
-#define                     nDCII  0x0       
 #define                    MINCII  0x8        /* Min Count Interrupt Identifier */
-#define                   nMINCII  0x0       
 #define                    MAXCII  0x10       /* Max Count Interrupt Identifier */
-#define                   nMAXCII  0x0       
 #define                   COV31II  0x20       /* Bit 31 Overflow Interrupt Identifier */
-#define                  nCOV31II  0x0       
 #define                   COV15II  0x40       /* Bit 15 Overflow Interrupt Identifier */
-#define                  nCOV15II  0x0       
 #define                   CZEROII  0x80       /* Count to Zero Interrupt Identifier */
-#define                  nCZEROII  0x0       
 #define                     CZMII  0x100      /* CZM Pin Interrupt Identifier */
-#define                    nCZMII  0x0       
 #define                    CZMEII  0x200      /* CZM Error Interrupt Identifier */
-#define                   nCZMEII  0x0       
 #define                    CZMZII  0x400      /* CZM Zeroes Counter Interrupt Identifier */
-#define                   nCZMZII  0x0       
 
 /* Bit masks for CNT_COMMAND */
 
 #define                    W1LMIN  0xf0       /* Load Min Register */
 #define                    W1LMAX  0xf00      /* Load Max Register */
 #define                  W1ZMONCE  0x1000     /* Enable CZM Clear Counter Once */
-#define                 nW1ZMONCE  0x0       
 
 /* Bit masks for CNT_DEBOUNCE */
 
 /* Bit masks for RTC_ICTL */
 
 #define STOPWATCH_INTERRUPT_ENABLE  0x1        /* Stopwatch Interrupt Enable */
-#define nSTOPWATCH_INTERRUPT_ENABLE  0x0       
 #define    ALARM_INTERRUPT_ENABLE  0x2        /* Alarm Interrupt Enable */
-#define   nALARM_INTERRUPT_ENABLE  0x0       
 #define  SECONDS_INTERRUPT_ENABLE  0x4        /* Seconds Interrupt Enable */
-#define nSECONDS_INTERRUPT_ENABLE  0x0       
 #define  MINUTES_INTERRUPT_ENABLE  0x8        /* Minutes Interrupt Enable */
-#define nMINUTES_INTERRUPT_ENABLE  0x0       
 #define    HOURS_INTERRUPT_ENABLE  0x10       /* Hours Interrupt Enable */
-#define   nHOURS_INTERRUPT_ENABLE  0x0       
 #define TWENTY_FOUR_HOURS_INTERRUPT_ENABLE  0x20       /* 24 Hours Interrupt Enable */
-#define nTWENTY_FOUR_HOURS_INTERRUPT_ENABLE  0x0       
 #define DAY_ALARM_INTERRUPT_ENABLE  0x40       /* Day Alarm Interrupt Enable */
-#define nDAY_ALARM_INTERRUPT_ENABLE  0x0       
 #define WRITE_COMPLETE_INTERRUPT_ENABLE  0x8000     /* Write Complete Interrupt Enable */
-#define nWRITE_COMPLETE_INTERRUPT_ENABLE  0x0       
 
 /* Bit masks for RTC_ISTAT */
 
 #define      STOPWATCH_EVENT_FLAG  0x1        /* Stopwatch Event Flag */
-#define     nSTOPWATCH_EVENT_FLAG  0x0       
 #define          ALARM_EVENT_FLAG  0x2        /* Alarm Event Flag */
-#define         nALARM_EVENT_FLAG  0x0       
 #define        SECONDS_EVENT_FLAG  0x4        /* Seconds Event Flag */
-#define       nSECONDS_EVENT_FLAG  0x0       
 #define        MINUTES_EVENT_FLAG  0x8        /* Minutes Event Flag */
-#define       nMINUTES_EVENT_FLAG  0x0       
 #define          HOURS_EVENT_FLAG  0x10       /* Hours Event Flag */
-#define         nHOURS_EVENT_FLAG  0x0       
 #define TWENTY_FOUR_HOURS_EVENT_FLAG  0x20       /* 24 Hours Event Flag */
-#define nTWENTY_FOUR_HOURS_EVENT_FLAG  0x0       
 #define      DAY_ALARM_EVENT_FLAG  0x40       /* Day Alarm Event Flag */
-#define     nDAY_ALARM_EVENT_FLAG  0x0       
 #define     WRITE_PENDING__STATUS  0x4000     /* Write Pending  Status */
-#define    nWRITE_PENDING__STATUS  0x0       
 #define            WRITE_COMPLETE  0x8000     /* Write Complete */
-#define           nWRITE_COMPLETE  0x0       
 
 /* Bit masks for RTC_SWCNT */
 
 /* Bit masks for RTC_PREN */
 
 #define                      PREN  0x1        /* Prescaler Enable */
-#define                     nPREN  0x0       
 
 /* Bit masks for OTP_CONTROL */
 
 #define                FUSE_FADDR  0x1ff      /* OTP/Fuse Address */
 #define                      FIEN  0x800      /* OTP/Fuse Interrupt Enable */
-#define                     nFIEN  0x0       
 #define                  FTESTDEC  0x1000     /* OTP/Fuse Test Decoder */
-#define                 nFTESTDEC  0x0       
 #define                   FWRTEST  0x2000     /* OTP/Fuse Write Test */
-#define                  nFWRTEST  0x0       
 #define                     FRDEN  0x4000     /* OTP/Fuse Read Enable */
-#define                    nFRDEN  0x0       
 #define                     FWREN  0x8000     /* OTP/Fuse Write Enable */
-#define                    nFWREN  0x0       
 
 /* Bit masks for OTP_BEN */
 
 /* Bit masks for OTP_STATUS */
 
 #define                     FCOMP  0x1        /* OTP/Fuse Access Complete */
-#define                    nFCOMP  0x0       
 #define                    FERROR  0x2        /* OTP/Fuse Access Error */
-#define                   nFERROR  0x0       
 #define                  MMRGLOAD  0x10       /* Memory Mapped Register Gasket Load */
-#define                 nMMRGLOAD  0x0       
 #define                  MMRGLOCK  0x20       /* Memory Mapped Register Gasket Lock */
-#define                 nMMRGLOCK  0x0       
 #define                    FPGMEN  0x40       /* OTP/Fuse Program Enable */
-#define                   nFPGMEN  0x0       
 
 /* Bit masks for OTP_TIMING */
 
 /* Bit masks for SECURE_SYSSWT */
 
 #define                   EMUDABL  0x1        /* Emulation Disable. */
-#define                  nEMUDABL  0x0       
 #define                   RSTDABL  0x2        /* Reset Disable */
-#define                  nRSTDABL  0x0       
 #define                   L1IDABL  0x1c       /* L1 Instruction Memory Disable. */
 #define                  L1DADABL  0xe0       /* L1 Data Bank A Memory Disable. */
 #define                  L1DBDABL  0x700      /* L1 Data Bank B Memory Disable. */
 #define                   DMA0OVR  0x800      /* DMA0 Memory Access Override */
-#define                  nDMA0OVR  0x0       
 #define                   DMA1OVR  0x1000     /* DMA1 Memory Access Override */
-#define                  nDMA1OVR  0x0       
 #define                    EMUOVR  0x4000     /* Emulation Override */
-#define                   nEMUOVR  0x0       
 #define                    OTPSEN  0x8000     /* OTP Secrets Enable. */
-#define                   nOTPSEN  0x0       
 #define                    L2DABL  0x70000    /* L2 Memory Disable. */
 
 /* Bit masks for SECURE_CONTROL */
 
 #define                   SECURE0  0x1        /* SECURE 0 */
-#define                  nSECURE0  0x0       
 #define                   SECURE1  0x2        /* SECURE 1 */
-#define                  nSECURE1  0x0       
 #define                   SECURE2  0x4        /* SECURE 2 */
-#define                  nSECURE2  0x0       
 #define                   SECURE3  0x8        /* SECURE 3 */
-#define                  nSECURE3  0x0       
 
 /* Bit masks for SECURE_STATUS */
 
 #define                   SECMODE  0x3        /* Secured Mode Control State */
 #define                       NMI  0x4        /* Non Maskable Interrupt */
-#define                      nNMI  0x0       
 #define                   AFVALID  0x8        /* Authentication Firmware Valid */
-#define                  nAFVALID  0x0       
 #define                    AFEXIT  0x10       /* Authentication Firmware Exit */
-#define                   nAFEXIT  0x0       
 #define                   SECSTAT  0xe0       /* Secure Status */
 
 /* Bit masks for PLL_DIV */
 
 #define                      MSEL  0x7e00     /* Multiplier Select */
 #define                    BYPASS  0x100      /* PLL Bypass Enable */
-#define                   nBYPASS  0x0       
 #define              OUTPUT_DELAY  0x80       /* External Memory Output Delay Enable */
-#define             nOUTPUT_DELAY  0x0       
 #define               INPUT_DELAY  0x40       /* External Memory Input Delay Enable */
-#define              nINPUT_DELAY  0x0       
 #define                      PDWN  0x20       /* Power Down */
-#define                     nPDWN  0x0       
 #define                    STOPCK  0x8        /* Stop Clock */
-#define                   nSTOPCK  0x0       
 #define                   PLL_OFF  0x2        /* Disable PLL */
-#define                  nPLL_OFF  0x0       
 #define                        DF  0x1        /* Divide Frequency */
-#define                       nDF  0x0       
 
 /* Bit masks for PLL_STAT */
 
 #define                PLL_LOCKED  0x20       /* PLL Locked Status */
-#define               nPLL_LOCKED  0x0       
 #define        ACTIVE_PLLDISABLED  0x4        /* Active Mode With PLL Disabled */
-#define       nACTIVE_PLLDISABLED  0x0       
 #define                   FULL_ON  0x2        /* Full-On Mode */
-#define                  nFULL_ON  0x0       
 #define         ACTIVE_PLLENABLED  0x1        /* Active Mode With PLL Enabled */
-#define        nACTIVE_PLLENABLED  0x0       
 #define                     RTCWS  0x400      /* RTC/Reset Wake-Up Status */
-#define                    nRTCWS  0x0       
 #define                     CANWS  0x800      /* CAN Wake-Up Status */
-#define                    nCANWS  0x0       
 #define                     USBWS  0x2000     /* USB Wake-Up Status */
-#define                    nUSBWS  0x0       
 #define                    KPADWS  0x4000     /* Keypad Wake-Up Status */
-#define                   nKPADWS  0x0       
 #define                     ROTWS  0x8000     /* Rotary Wake-Up Status */
-#define                    nROTWS  0x0       
 #define                      GPWS  0x1000     /* General-Purpose Wake-Up Status */
-#define                     nGPWS  0x0       
 
 /* Bit masks for VR_CTL */
 
 #define                      GAIN  0xc        /* Voltage Output Level Gain */
 #define                      VLEV  0xf0       /* Internal Voltage Level */
 #define                   SCKELOW  0x8000     /* Drive SCKE Low During Reset Enable */
-#define                  nSCKELOW  0x0       
 #define                      WAKE  0x100      /* RTC/Reset Wake-Up Enable */
-#define                     nWAKE  0x0       
 #define                     CANWE  0x200      /* CAN0/1 Wake-Up Enable */
-#define                    nCANWE  0x0       
 #define                      GPWE  0x400      /* General-Purpose Wake-Up Enable */
-#define                     nGPWE  0x0       
 #define                     USBWE  0x800      /* USB Wake-Up Enable */
-#define                    nUSBWE  0x0       
 #define                    KPADWE  0x1000     /* Keypad Wake-Up Enable */
-#define                   nKPADWE  0x0       
 #define                     ROTWE  0x2000     /* Rotary Wake-Up Enable */
-#define                    nROTWE  0x0       
 
 /* Bit masks for NFC_CTL */
 
 #define                    WR_DLY  0xf        /* Write Strobe Delay */
 #define                    RD_DLY  0xf0       /* Read Strobe Delay */
 #define                    NWIDTH  0x100      /* NAND Data Width */
-#define                   nNWIDTH  0x0       
 #define                   PG_SIZE  0x200      /* Page Size */
-#define                  nPG_SIZE  0x0       
 
 /* Bit masks for NFC_STAT */
 
 #define                     NBUSY  0x1        /* Not Busy */
-#define                    nNBUSY  0x0       
 #define                   WB_FULL  0x2        /* Write Buffer Full */
-#define                  nWB_FULL  0x0       
 #define                PG_WR_STAT  0x4        /* Page Write Pending */
-#define               nPG_WR_STAT  0x0       
 #define                PG_RD_STAT  0x8        /* Page Read Pending */
-#define               nPG_RD_STAT  0x0       
 #define                  WB_EMPTY  0x10       /* Write Buffer Empty */
-#define                 nWB_EMPTY  0x0       
 
 /* Bit masks for NFC_IRQSTAT */
 
 #define                  NBUSYIRQ  0x1        /* Not Busy IRQ */
-#define                 nNBUSYIRQ  0x0       
 #define                    WB_OVF  0x2        /* Write Buffer Overflow */
-#define                   nWB_OVF  0x0       
 #define                   WB_EDGE  0x4        /* Write Buffer Edge Detect */
-#define                  nWB_EDGE  0x0       
 #define                    RD_RDY  0x8        /* Read Data Ready */
-#define                   nRD_RDY  0x0       
 #define                   WR_DONE  0x10       /* Page Write Done */
-#define                  nWR_DONE  0x0       
 
 /* Bit masks for NFC_IRQMASK */
 
 #define              MASK_BUSYIRQ  0x1        /* Mask Not Busy IRQ */
-#define             nMASK_BUSYIRQ  0x0       
 #define                MASK_WBOVF  0x2        /* Mask Write Buffer Overflow */
-#define               nMASK_WBOVF  0x0       
 #define              MASK_WBEMPTY  0x4        /* Mask Write Buffer Empty */
-#define             nMASK_WBEMPTY  0x0       
 #define                MASK_RDRDY  0x8        /* Mask Read Data Ready */
-#define               nMASK_RDRDY  0x0       
 #define               MASK_WRDONE  0x10       /* Mask Write Done */
-#define              nMASK_WRDONE  0x0       
 
 /* Bit masks for NFC_RST */
 
 #define                   ECC_RST  0x1        /* ECC (and NFC counters) Reset */
-#define                  nECC_RST  0x0       
 
 /* Bit masks for NFC_PGCTL */
 
 #define               PG_RD_START  0x1        /* Page Read Start */
-#define              nPG_RD_START  0x0       
 #define               PG_WR_START  0x2        /* Page Write Start */
-#define              nPG_WR_START  0x0       
 
 /* Bit masks for NFC_ECC0 */
 
 /* Bit masks for CAN0_CONTROL */
 
 #define                       SRS  0x1        /* Software Reset */
-#define                      nSRS  0x0       
 #define                       DNM  0x2        /* DeviceNet Mode */
-#define                      nDNM  0x0       
 #define                       ABO  0x4        /* Auto Bus On */
-#define                      nABO  0x0       
 #define                       WBA  0x10       /* Wakeup On CAN Bus Activity */
-#define                      nWBA  0x0       
 #define                       SMR  0x20       /* Sleep Mode Request */
-#define                      nSMR  0x0       
 #define                       CSR  0x40       /* CAN Suspend Mode Request */
-#define                      nCSR  0x0       
 #define                       CCR  0x80       /* CAN Configuration Mode Request */
-#define                      nCCR  0x0       
 
 /* Bit masks for CAN0_STATUS */
 
 #define                        WT  0x1        /* CAN Transmit Warning Flag */
-#define                       nWT  0x0       
 #define                        WR  0x2        /* CAN Receive Warning Flag */
-#define                       nWR  0x0       
 #define                        EP  0x4        /* CAN Error Passive Mode */
-#define                       nEP  0x0       
 #define                       EBO  0x8        /* CAN Error Bus Off Mode */
-#define                      nEBO  0x0       
 #define                       CSA  0x40       /* CAN Suspend Mode Acknowledge */
-#define                      nCSA  0x0       
 #define                       CCA  0x80       /* CAN Configuration Mode Acknowledge */
-#define                      nCCA  0x0       
 #define                     MBPTR  0x1f00     /* Mailbox Pointer */
 #define                       TRM  0x4000     /* Transmit Mode Status */
-#define                      nTRM  0x0       
 #define                       REC  0x8000     /* Receive Mode Status */
-#define                      nREC  0x0       
 
 /* Bit masks for CAN0_DEBUG */
 
 #define                       DEC  0x1        /* Disable Transmit/Receive Error Counters */
-#define                      nDEC  0x0       
 #define                       DRI  0x2        /* Disable CANRX Input Pin */
-#define                      nDRI  0x0       
 #define                       DTO  0x4        /* Disable CANTX Output Pin */
-#define                      nDTO  0x0       
 #define                       DIL  0x8        /* Disable Internal Loop */
-#define                      nDIL  0x0       
 #define                       MAA  0x10       /* Mode Auto-Acknowledge */
-#define                      nMAA  0x0       
 #define                       MRB  0x20       /* Mode Read Back */
-#define                      nMRB  0x0       
 #define                       CDE  0x8000     /* CAN Debug Mode Enable */
-#define                      nCDE  0x0       
 
 /* Bit masks for CAN0_CLOCK */
 
 
 #define                       SJW  0x300      /* Synchronization Jump Width */
 #define                       SAM  0x80       /* Sampling */
-#define                      nSAM  0x0       
 #define                     TSEG2  0x70       /* Time Segment 2 */
 #define                     TSEG1  0xf        /* Time Segment 1 */
 
 /* Bit masks for CAN0_INTR */
 
 #define                     CANRX  0x80       /* Serial Input From Transceiver */
-#define                    nCANRX  0x0       
 #define                     CANTX  0x40       /* Serial Output To Transceiver */
-#define                    nCANTX  0x0       
 #define                     SMACK  0x8        /* Sleep Mode Acknowledge */
-#define                    nSMACK  0x0       
 #define                      GIRQ  0x4        /* Global Interrupt Request Status */
-#define                     nGIRQ  0x0       
 #define                    MBTIRQ  0x2        /* Mailbox Transmit Interrupt Request */
-#define                   nMBTIRQ  0x0       
 #define                    MBRIRQ  0x1        /* Mailbox Receive Interrupt Request */
-#define                   nMBRIRQ  0x0       
 
 /* Bit masks for CAN0_GIM */
 
 #define                     EWTIM  0x1        /* Error Warning Transmit Interrupt Mask */
-#define                    nEWTIM  0x0       
 #define                     EWRIM  0x2        /* Error Warning Receive Interrupt Mask */
-#define                    nEWRIM  0x0       
 #define                      EPIM  0x4        /* Error Passive Interrupt Mask */
-#define                     nEPIM  0x0       
 #define                      BOIM  0x8        /* Bus Off Interrupt Mask */
-#define                     nBOIM  0x0       
 #define                      WUIM  0x10       /* Wakeup Interrupt Mask */
-#define                     nWUIM  0x0       
 #define                     UIAIM  0x20       /* Unimplemented Address Interrupt Mask */
-#define                    nUIAIM  0x0       
 #define                      AAIM  0x40       /* Abort Acknowledge Interrupt Mask */
-#define                     nAAIM  0x0       
 #define                     RMLIM  0x80       /* Receive Message Lost Interrupt Mask */
-#define                    nRMLIM  0x0       
 #define                     UCEIM  0x100      /* Universal Counter Exceeded Interrupt Mask */
-#define                    nUCEIM  0x0       
 #define                      ADIM  0x400      /* Access Denied Interrupt Mask */
-#define                     nADIM  0x0       
 
 /* Bit masks for CAN0_GIS */
 
 #define                     EWTIS  0x1        /* Error Warning Transmit Interrupt Status */
-#define                    nEWTIS  0x0       
 #define                     EWRIS  0x2        /* Error Warning Receive Interrupt Status */
-#define                    nEWRIS  0x0       
 #define                      EPIS  0x4        /* Error Passive Interrupt Status */
-#define                     nEPIS  0x0       
 #define                      BOIS  0x8        /* Bus Off Interrupt Status */
-#define                     nBOIS  0x0       
 #define                      WUIS  0x10       /* Wakeup Interrupt Status */
-#define                     nWUIS  0x0       
 #define                     UIAIS  0x20       /* Unimplemented Address Interrupt Status */
-#define                    nUIAIS  0x0       
 #define                      AAIS  0x40       /* Abort Acknowledge Interrupt Status */
-#define                     nAAIS  0x0       
 #define                     RMLIS  0x80       /* Receive Message Lost Interrupt Status */
-#define                    nRMLIS  0x0       
 #define                     UCEIS  0x100      /* Universal Counter Exceeded Interrupt Status */
-#define                    nUCEIS  0x0       
 #define                      ADIS  0x400      /* Access Denied Interrupt Status */
-#define                     nADIS  0x0       
 
 /* Bit masks for CAN0_GIF */
 
 #define                     EWTIF  0x1        /* Error Warning Transmit Interrupt Flag */
-#define                    nEWTIF  0x0       
 #define                     EWRIF  0x2        /* Error Warning Receive Interrupt Flag */
-#define                    nEWRIF  0x0       
 #define                      EPIF  0x4        /* Error Passive Interrupt Flag */
-#define                     nEPIF  0x0       
 #define                      BOIF  0x8        /* Bus Off Interrupt Flag */
-#define                     nBOIF  0x0       
 #define                      WUIF  0x10       /* Wakeup Interrupt Flag */
-#define                     nWUIF  0x0       
 #define                     UIAIF  0x20       /* Unimplemented Address Interrupt Flag */
-#define                    nUIAIF  0x0       
 #define                      AAIF  0x40       /* Abort Acknowledge Interrupt Flag */
-#define                     nAAIF  0x0       
 #define                     RMLIF  0x80       /* Receive Message Lost Interrupt Flag */
-#define                    nRMLIF  0x0       
 #define                     UCEIF  0x100      /* Universal Counter Exceeded Interrupt Flag */
-#define                    nUCEIF  0x0       
 #define                      ADIF  0x400      /* Access Denied Interrupt Flag */
-#define                     nADIF  0x0       
 
 /* Bit masks for CAN0_MBTD */
 
 #define                       TDR  0x80       /* Temporary Disable Request */
-#define                      nTDR  0x0       
 #define                       TDA  0x40       /* Temporary Disable Acknowledge */
-#define                      nTDA  0x0       
 #define                     TDPTR  0x1f       /* Temporary Disable Pointer */
 
 /* Bit masks for CAN0_UCCNF */
 
 #define                     UCCNF  0xf        /* Universal Counter Configuration */
 #define                      UCRC  0x20       /* Universal Counter Reload/Clear */
-#define                     nUCRC  0x0       
 #define                      UCCT  0x40       /* Universal Counter CAN Trigger */
-#define                     nUCCT  0x0       
 #define                       UCE  0x80       /* Universal Counter Enable */
-#define                      nUCE  0x0       
 
 /* Bit masks for CAN0_UCCNT */
 
 /* Bit masks for CAN0_ESR */
 
 #define                       FER  0x80       /* Form Error */
-#define                      nFER  0x0       
 #define                       BEF  0x40       /* Bit Error Flag */
-#define                      nBEF  0x0       
 #define                       SA0  0x20       /* Stuck At Dominant */
-#define                      nSA0  0x0       
 #define                      CRCE  0x10       /* CRC Error */
-#define                     nCRCE  0x0       
 #define                       SER  0x8        /* Stuff Bit Error */
-#define                      nSER  0x0       
 #define                      ACKE  0x4        /* Acknowledge Error */
-#define                     nACKE  0x0       
 
 /* Bit masks for CAN0_EWR */
 
 /* Bit masks for CAN0_AMxx_H */
 
 #define                       FDF  0x8000     /* Filter On Data Field */
-#define                      nFDF  0x0       
 #define                       FMD  0x4000     /* Full Mask Data */
-#define                      nFMD  0x0       
 #define                     AMIDE  0x2000     /* Acceptance Mask Identifier Extension */
-#define                    nAMIDE  0x0       
 #define                    BASEID  0x1ffc     /* Base Identifier */
 #define                  EXTID_HI  0x3        /* Extended Identifier High Bits */
 
 /* Bit masks for CAN0_MBxx_ID1 */
 
 #define                       AME  0x8000     /* Acceptance Mask Enable */
-#define                      nAME  0x0       
 #define                       RTR  0x4000     /* Remote Transmission Request */
-#define                      nRTR  0x0       
 #define                       IDE  0x2000     /* Identifier Extension */
-#define                      nIDE  0x0       
 #define                    BASEID  0x1ffc     /* Base Identifier */
 #define                  EXTID_HI  0x3        /* Extended Identifier High Bits */
 
 /* Bit masks for CAN0_MC1 */
 
 #define                       MC0  0x1        /* Mailbox 0 Enable */
-#define                      nMC0  0x0       
 #define                       MC1  0x2        /* Mailbox 1 Enable */
-#define                      nMC1  0x0       
 #define                       MC2  0x4        /* Mailbox 2 Enable */
-#define                      nMC2  0x0       
 #define                       MC3  0x8        /* Mailbox 3 Enable */
-#define                      nMC3  0x0       
 #define                       MC4  0x10       /* Mailbox 4 Enable */
-#define                      nMC4  0x0       
 #define                       MC5  0x20       /* Mailbox 5 Enable */
-#define                      nMC5  0x0       
 #define                       MC6  0x40       /* Mailbox 6 Enable */
-#define                      nMC6  0x0       
 #define                       MC7  0x80       /* Mailbox 7 Enable */
-#define                      nMC7  0x0       
 #define                       MC8  0x100      /* Mailbox 8 Enable */
-#define                      nMC8  0x0       
 #define                       MC9  0x200      /* Mailbox 9 Enable */
-#define                      nMC9  0x0       
 #define                      MC10  0x400      /* Mailbox 10 Enable */
-#define                     nMC10  0x0       
 #define                      MC11  0x800      /* Mailbox 11 Enable */
-#define                     nMC11  0x0       
 #define                      MC12  0x1000     /* Mailbox 12 Enable */
-#define                     nMC12  0x0       
 #define                      MC13  0x2000     /* Mailbox 13 Enable */
-#define                     nMC13  0x0       
 #define                      MC14  0x4000     /* Mailbox 14 Enable */
-#define                     nMC14  0x0       
 #define                      MC15  0x8000     /* Mailbox 15 Enable */
-#define                     nMC15  0x0       
 
 /* Bit masks for CAN0_MC2 */
 
 #define                      MC16  0x1        /* Mailbox 16 Enable */
-#define                     nMC16  0x0       
 #define                      MC17  0x2        /* Mailbox 17 Enable */
-#define                     nMC17  0x0       
 #define                      MC18  0x4        /* Mailbox 18 Enable */
-#define                     nMC18  0x0       
 #define                      MC19  0x8        /* Mailbox 19 Enable */
-#define                     nMC19  0x0       
 #define                      MC20  0x10       /* Mailbox 20 Enable */
-#define                     nMC20  0x0       
 #define                      MC21  0x20       /* Mailbox 21 Enable */
-#define                     nMC21  0x0       
 #define                      MC22  0x40       /* Mailbox 22 Enable */
-#define                     nMC22  0x0       
 #define                      MC23  0x80       /* Mailbox 23 Enable */
-#define                     nMC23  0x0       
 #define                      MC24  0x100      /* Mailbox 24 Enable */
-#define                     nMC24  0x0       
 #define                      MC25  0x200      /* Mailbox 25 Enable */
-#define                     nMC25  0x0       
 #define                      MC26  0x400      /* Mailbox 26 Enable */
-#define                     nMC26  0x0       
 #define                      MC27  0x800      /* Mailbox 27 Enable */
-#define                     nMC27  0x0       
 #define                      MC28  0x1000     /* Mailbox 28 Enable */
-#define                     nMC28  0x0       
 #define                      MC29  0x2000     /* Mailbox 29 Enable */
-#define                     nMC29  0x0       
 #define                      MC30  0x4000     /* Mailbox 30 Enable */
-#define                     nMC30  0x0       
 #define                      MC31  0x8000     /* Mailbox 31 Enable */
-#define                     nMC31  0x0       
 
 /* Bit masks for CAN0_MD1 */
 
 #define                       MD0  0x1        /* Mailbox 0 Receive Enable */
-#define                      nMD0  0x0       
 #define                       MD1  0x2        /* Mailbox 1 Receive Enable */
-#define                      nMD1  0x0       
 #define                       MD2  0x4        /* Mailbox 2 Receive Enable */
-#define                      nMD2  0x0       
 #define                       MD3  0x8        /* Mailbox 3 Receive Enable */
-#define                      nMD3  0x0       
 #define                       MD4  0x10       /* Mailbox 4 Receive Enable */
-#define                      nMD4  0x0       
 #define                       MD5  0x20       /* Mailbox 5 Receive Enable */
-#define                      nMD5  0x0       
 #define                       MD6  0x40       /* Mailbox 6 Receive Enable */
-#define                      nMD6  0x0       
 #define                       MD7  0x80       /* Mailbox 7 Receive Enable */
-#define                      nMD7  0x0       
 #define                       MD8  0x100      /* Mailbox 8 Receive Enable */
-#define                      nMD8  0x0       
 #define                       MD9  0x200      /* Mailbox 9 Receive Enable */
-#define                      nMD9  0x0       
 #define                      MD10  0x400      /* Mailbox 10 Receive Enable */
-#define                     nMD10  0x0       
 #define                      MD11  0x800      /* Mailbox 11 Receive Enable */
-#define                     nMD11  0x0       
 #define                      MD12  0x1000     /* Mailbox 12 Receive Enable */
-#define                     nMD12  0x0       
 #define                      MD13  0x2000     /* Mailbox 13 Receive Enable */
-#define                     nMD13  0x0       
 #define                      MD14  0x4000     /* Mailbox 14 Receive Enable */
-#define                     nMD14  0x0       
 #define                      MD15  0x8000     /* Mailbox 15 Receive Enable */
-#define                     nMD15  0x0       
 
 /* Bit masks for CAN0_MD2 */
 
 #define                      MD16  0x1        /* Mailbox 16 Receive Enable */
-#define                     nMD16  0x0       
 #define                      MD17  0x2        /* Mailbox 17 Receive Enable */
-#define                     nMD17  0x0       
 #define                      MD18  0x4        /* Mailbox 18 Receive Enable */
-#define                     nMD18  0x0       
 #define                      MD19  0x8        /* Mailbox 19 Receive Enable */
-#define                     nMD19  0x0       
 #define                      MD20  0x10       /* Mailbox 20 Receive Enable */
-#define                     nMD20  0x0       
 #define                      MD21  0x20       /* Mailbox 21 Receive Enable */
-#define                     nMD21  0x0       
 #define                      MD22  0x40       /* Mailbox 22 Receive Enable */
-#define                     nMD22  0x0       
 #define                      MD23  0x80       /* Mailbox 23 Receive Enable */
-#define                     nMD23  0x0       
 #define                      MD24  0x100      /* Mailbox 24 Receive Enable */
-#define                     nMD24  0x0       
 #define                      MD25  0x200      /* Mailbox 25 Receive Enable */
-#define                     nMD25  0x0       
 #define                      MD26  0x400      /* Mailbox 26 Receive Enable */
-#define                     nMD26  0x0       
 #define                      MD27  0x800      /* Mailbox 27 Receive Enable */
-#define                     nMD27  0x0       
 #define                      MD28  0x1000     /* Mailbox 28 Receive Enable */
-#define                     nMD28  0x0       
 #define                      MD29  0x2000     /* Mailbox 29 Receive Enable */
-#define                     nMD29  0x0       
 #define                      MD30  0x4000     /* Mailbox 30 Receive Enable */
-#define                     nMD30  0x0       
 #define                      MD31  0x8000     /* Mailbox 31 Receive Enable */
-#define                     nMD31  0x0       
 
 /* Bit masks for CAN0_RMP1 */
 
 #define                      RMP0  0x1        /* Mailbox 0 Receive Message Pending */
-#define                     nRMP0  0x0       
 #define                      RMP1  0x2        /* Mailbox 1 Receive Message Pending */
-#define                     nRMP1  0x0       
 #define                      RMP2  0x4        /* Mailbox 2 Receive Message Pending */
-#define                     nRMP2  0x0       
 #define                      RMP3  0x8        /* Mailbox 3 Receive Message Pending */
-#define                     nRMP3  0x0       
 #define                      RMP4  0x10       /* Mailbox 4 Receive Message Pending */
-#define                     nRMP4  0x0       
 #define                      RMP5  0x20       /* Mailbox 5 Receive Message Pending */
-#define                     nRMP5  0x0       
 #define                      RMP6  0x40       /* Mailbox 6 Receive Message Pending */
-#define                     nRMP6  0x0       
 #define                      RMP7  0x80       /* Mailbox 7 Receive Message Pending */
-#define                     nRMP7  0x0       
 #define                      RMP8  0x100      /* Mailbox 8 Receive Message Pending */
-#define                     nRMP8  0x0       
 #define                      RMP9  0x200      /* Mailbox 9 Receive Message Pending */
-#define                     nRMP9  0x0       
 #define                     RMP10  0x400      /* Mailbox 10 Receive Message Pending */
-#define                    nRMP10  0x0       
 #define                     RMP11  0x800      /* Mailbox 11 Receive Message Pending */
-#define                    nRMP11  0x0       
 #define                     RMP12  0x1000     /* Mailbox 12 Receive Message Pending */
-#define                    nRMP12  0x0       
 #define                     RMP13  0x2000     /* Mailbox 13 Receive Message Pending */
-#define                    nRMP13  0x0       
 #define                     RMP14  0x4000     /* Mailbox 14 Receive Message Pending */
-#define                    nRMP14  0x0       
 #define                     RMP15  0x8000     /* Mailbox 15 Receive Message Pending */
-#define                    nRMP15  0x0       
 
 /* Bit masks for CAN0_RMP2 */
 
 #define                     RMP16  0x1        /* Mailbox 16 Receive Message Pending */
-#define                    nRMP16  0x0       
 #define                     RMP17  0x2        /* Mailbox 17 Receive Message Pending */
-#define                    nRMP17  0x0       
 #define                     RMP18  0x4        /* Mailbox 18 Receive Message Pending */
-#define                    nRMP18  0x0       
 #define                     RMP19  0x8        /* Mailbox 19 Receive Message Pending */
-#define                    nRMP19  0x0       
 #define                     RMP20  0x10       /* Mailbox 20 Receive Message Pending */
-#define                    nRMP20  0x0       
 #define                     RMP21  0x20       /* Mailbox 21 Receive Message Pending */
-#define                    nRMP21  0x0       
 #define                     RMP22  0x40       /* Mailbox 22 Receive Message Pending */
-#define                    nRMP22  0x0       
 #define                     RMP23  0x80       /* Mailbox 23 Receive Message Pending */
-#define                    nRMP23  0x0       
 #define                     RMP24  0x100      /* Mailbox 24 Receive Message Pending */
-#define                    nRMP24  0x0       
 #define                     RMP25  0x200      /* Mailbox 25 Receive Message Pending */
-#define                    nRMP25  0x0       
 #define                     RMP26  0x400      /* Mailbox 26 Receive Message Pending */
-#define                    nRMP26  0x0       
 #define                     RMP27  0x800      /* Mailbox 27 Receive Message Pending */
-#define                    nRMP27  0x0       
 #define                     RMP28  0x1000     /* Mailbox 28 Receive Message Pending */
-#define                    nRMP28  0x0       
 #define                     RMP29  0x2000     /* Mailbox 29 Receive Message Pending */
-#define                    nRMP29  0x0       
 #define                     RMP30  0x4000     /* Mailbox 30 Receive Message Pending */
-#define                    nRMP30  0x0       
 #define                     RMP31  0x8000     /* Mailbox 31 Receive Message Pending */
-#define                    nRMP31  0x0       
 
 /* Bit masks for CAN0_RML1 */
 
 #define                      RML0  0x1        /* Mailbox 0 Receive Message Lost */
-#define                     nRML0  0x0       
 #define                      RML1  0x2        /* Mailbox 1 Receive Message Lost */
-#define                     nRML1  0x0       
 #define                      RML2  0x4        /* Mailbox 2 Receive Message Lost */
-#define                     nRML2  0x0       
 #define                      RML3  0x8        /* Mailbox 3 Receive Message Lost */
-#define                     nRML3  0x0       
 #define                      RML4  0x10       /* Mailbox 4 Receive Message Lost */
-#define                     nRML4  0x0       
 #define                      RML5  0x20       /* Mailbox 5 Receive Message Lost */
-#define                     nRML5  0x0       
 #define                      RML6  0x40       /* Mailbox 6 Receive Message Lost */
-#define                     nRML6  0x0       
 #define                      RML7  0x80       /* Mailbox 7 Receive Message Lost */
-#define                     nRML7  0x0       
 #define                      RML8  0x100      /* Mailbox 8 Receive Message Lost */
-#define                     nRML8  0x0       
 #define                      RML9  0x200      /* Mailbox 9 Receive Message Lost */
-#define                     nRML9  0x0       
 #define                     RML10  0x400      /* Mailbox 10 Receive Message Lost */
-#define                    nRML10  0x0       
 #define                     RML11  0x800      /* Mailbox 11 Receive Message Lost */
-#define                    nRML11  0x0       
 #define                     RML12  0x1000     /* Mailbox 12 Receive Message Lost */
-#define                    nRML12  0x0       
 #define                     RML13  0x2000     /* Mailbox 13 Receive Message Lost */
-#define                    nRML13  0x0       
 #define                     RML14  0x4000     /* Mailbox 14 Receive Message Lost */
-#define                    nRML14  0x0       
 #define                     RML15  0x8000     /* Mailbox 15 Receive Message Lost */
-#define                    nRML15  0x0       
 
 /* Bit masks for CAN0_RML2 */
 
 #define                     RML16  0x1        /* Mailbox 16 Receive Message Lost */
-#define                    nRML16  0x0       
 #define                     RML17  0x2        /* Mailbox 17 Receive Message Lost */
-#define                    nRML17  0x0       
 #define                     RML18  0x4        /* Mailbox 18 Receive Message Lost */
-#define                    nRML18  0x0       
 #define                     RML19  0x8        /* Mailbox 19 Receive Message Lost */
-#define                    nRML19  0x0       
 #define                     RML20  0x10       /* Mailbox 20 Receive Message Lost */
-#define                    nRML20  0x0       
 #define                     RML21  0x20       /* Mailbox 21 Receive Message Lost */
-#define                    nRML21  0x0       
 #define                     RML22  0x40       /* Mailbox 22 Receive Message Lost */
-#define                    nRML22  0x0       
 #define                     RML23  0x80       /* Mailbox 23 Receive Message Lost */
-#define                    nRML23  0x0       
 #define                     RML24  0x100      /* Mailbox 24 Receive Message Lost */
-#define                    nRML24  0x0       
 #define                     RML25  0x200      /* Mailbox 25 Receive Message Lost */
-#define                    nRML25  0x0       
 #define                     RML26  0x400      /* Mailbox 26 Receive Message Lost */
-#define                    nRML26  0x0       
 #define                     RML27  0x800      /* Mailbox 27 Receive Message Lost */
-#define                    nRML27  0x0       
 #define                     RML28  0x1000     /* Mailbox 28 Receive Message Lost */
-#define                    nRML28  0x0       
 #define                     RML29  0x2000     /* Mailbox 29 Receive Message Lost */
-#define                    nRML29  0x0       
 #define                     RML30  0x4000     /* Mailbox 30 Receive Message Lost */
-#define                    nRML30  0x0       
 #define                     RML31  0x8000     /* Mailbox 31 Receive Message Lost */
-#define                    nRML31  0x0       
 
 /* Bit masks for CAN0_OPSS1 */
 
 #define                     OPSS0  0x1        /* Mailbox 0 Overwrite Protection/Single-Shot Transmission Enable */
-#define                    nOPSS0  0x0       
 #define                     OPSS1  0x2        /* Mailbox 1 Overwrite Protection/Single-Shot Transmission Enable */
-#define                    nOPSS1  0x0       
 #define                     OPSS2  0x4        /* Mailbox 2 Overwrite Protection/Single-Shot Transmission Enable */
-#define                    nOPSS2  0x0       
 #define                     OPSS3  0x8        /* Mailbox 3 Overwrite Protection/Single-Shot Transmission Enable */
-#define                    nOPSS3  0x0       
 #define                     OPSS4  0x10       /* Mailbox 4 Overwrite Protection/Single-Shot Transmission Enable */
-#define                    nOPSS4  0x0       
 #define                     OPSS5  0x20       /* Mailbox 5 Overwrite Protection/Single-Shot Transmission Enable */
-#define                    nOPSS5  0x0       
 #define                     OPSS6  0x40       /* Mailbox 6 Overwrite Protection/Single-Shot Transmission Enable */
-#define                    nOPSS6  0x0       
 #define                     OPSS7  0x80       /* Mailbox 7 Overwrite Protection/Single-Shot Transmission Enable */
-#define                    nOPSS7  0x0       
 #define                     OPSS8  0x100      /* Mailbox 8 Overwrite Protection/Single-Shot Transmission Enable */
-#define                    nOPSS8  0x0       
 #define                     OPSS9  0x200      /* Mailbox 9 Overwrite Protection/Single-Shot Transmission Enable */
-#define                    nOPSS9  0x0       
 #define                    OPSS10  0x400      /* Mailbox 10 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS10  0x0       
 #define                    OPSS11  0x800      /* Mailbox 11 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS11  0x0       
 #define                    OPSS12  0x1000     /* Mailbox 12 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS12  0x0       
 #define                    OPSS13  0x2000     /* Mailbox 13 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS13  0x0       
 #define                    OPSS14  0x4000     /* Mailbox 14 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS14  0x0       
 #define                    OPSS15  0x8000     /* Mailbox 15 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS15  0x0       
 
 /* Bit masks for CAN0_OPSS2 */
 
 #define                    OPSS16  0x1        /* Mailbox 16 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS16  0x0       
 #define                    OPSS17  0x2        /* Mailbox 17 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS17  0x0       
 #define                    OPSS18  0x4        /* Mailbox 18 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS18  0x0       
 #define                    OPSS19  0x8        /* Mailbox 19 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS19  0x0       
 #define                    OPSS20  0x10       /* Mailbox 20 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS20  0x0       
 #define                    OPSS21  0x20       /* Mailbox 21 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS21  0x0       
 #define                    OPSS22  0x40       /* Mailbox 22 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS22  0x0       
 #define                    OPSS23  0x80       /* Mailbox 23 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS23  0x0       
 #define                    OPSS24  0x100      /* Mailbox 24 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS24  0x0       
 #define                    OPSS25  0x200      /* Mailbox 25 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS25  0x0       
 #define                    OPSS26  0x400      /* Mailbox 26 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS26  0x0       
 #define                    OPSS27  0x800      /* Mailbox 27 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS27  0x0       
 #define                    OPSS28  0x1000     /* Mailbox 28 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS28  0x0       
 #define                    OPSS29  0x2000     /* Mailbox 29 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS29  0x0       
 #define                    OPSS30  0x4000     /* Mailbox 30 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS30  0x0       
 #define                    OPSS31  0x8000     /* Mailbox 31 Overwrite Protection/Single-Shot Transmission Enable */
-#define                   nOPSS31  0x0       
 
 /* Bit masks for CAN0_TRS1 */
 
 #define                      TRS0  0x1        /* Mailbox 0 Transmit Request Set */
-#define                     nTRS0  0x0       
 #define                      TRS1  0x2        /* Mailbox 1 Transmit Request Set */
-#define                     nTRS1  0x0       
 #define                      TRS2  0x4        /* Mailbox 2 Transmit Request Set */
-#define                     nTRS2  0x0       
 #define                      TRS3  0x8        /* Mailbox 3 Transmit Request Set */
-#define                     nTRS3  0x0       
 #define                      TRS4  0x10       /* Mailbox 4 Transmit Request Set */
-#define                     nTRS4  0x0       
 #define                      TRS5  0x20       /* Mailbox 5 Transmit Request Set */
-#define                     nTRS5  0x0       
 #define                      TRS6  0x40       /* Mailbox 6 Transmit Request Set */
-#define                     nTRS6  0x0       
 #define                      TRS7  0x80       /* Mailbox 7 Transmit Request Set */
-#define                     nTRS7  0x0       
 #define                      TRS8  0x100      /* Mailbox 8 Transmit Request Set */
-#define                     nTRS8  0x0       
 #define                      TRS9  0x200      /* Mailbox 9 Transmit Request Set */
-#define                     nTRS9  0x0       
 #define                     TRS10  0x400      /* Mailbox 10 Transmit Request Set */
-#define                    nTRS10  0x0       
 #define                     TRS11  0x800      /* Mailbox 11 Transmit Request Set */
-#define                    nTRS11  0x0       
 #define                     TRS12  0x1000     /* Mailbox 12 Transmit Request Set */
-#define                    nTRS12  0x0       
 #define                     TRS13  0x2000     /* Mailbox 13 Transmit Request Set */
-#define                    nTRS13  0x0       
 #define                     TRS14  0x4000     /* Mailbox 14 Transmit Request Set */
-#define                    nTRS14  0x0       
 #define                     TRS15  0x8000     /* Mailbox 15 Transmit Request Set */
-#define                    nTRS15  0x0       
 
 /* Bit masks for CAN0_TRS2 */
 
 #define                     TRS16  0x1        /* Mailbox 16 Transmit Request Set */
-#define                    nTRS16  0x0       
 #define                     TRS17  0x2        /* Mailbox 17 Transmit Request Set */
-#define                    nTRS17  0x0       
 #define                     TRS18  0x4        /* Mailbox 18 Transmit Request Set */
-#define                    nTRS18  0x0       
 #define                     TRS19  0x8        /* Mailbox 19 Transmit Request Set */
-#define                    nTRS19  0x0       
 #define                     TRS20  0x10       /* Mailbox 20 Transmit Request Set */
-#define                    nTRS20  0x0       
 #define                     TRS21  0x20       /* Mailbox 21 Transmit Request Set */
-#define                    nTRS21  0x0       
 #define                     TRS22  0x40       /* Mailbox 22 Transmit Request Set */
-#define                    nTRS22  0x0       
 #define                     TRS23  0x80       /* Mailbox 23 Transmit Request Set */
-#define                    nTRS23  0x0       
 #define                     TRS24  0x100      /* Mailbox 24 Transmit Request Set */
-#define                    nTRS24  0x0       
 #define                     TRS25  0x200      /* Mailbox 25 Transmit Request Set */
-#define                    nTRS25  0x0       
 #define                     TRS26  0x400      /* Mailbox 26 Transmit Request Set */
-#define                    nTRS26  0x0       
 #define                     TRS27  0x800      /* Mailbox 27 Transmit Request Set */
-#define                    nTRS27  0x0       
 #define                     TRS28  0x1000     /* Mailbox 28 Transmit Request Set */
-#define                    nTRS28  0x0       
 #define                     TRS29  0x2000     /* Mailbox 29 Transmit Request Set */
-#define                    nTRS29  0x0       
 #define                     TRS30  0x4000     /* Mailbox 30 Transmit Request Set */
-#define                    nTRS30  0x0       
 #define                     TRS31  0x8000     /* Mailbox 31 Transmit Request Set */
-#define                    nTRS31  0x0       
 
 /* Bit masks for CAN0_TRR1 */
 
 #define                      TRR0  0x1        /* Mailbox 0 Transmit Request Reset */
-#define                     nTRR0  0x0       
 #define                      TRR1  0x2        /* Mailbox 1 Transmit Request Reset */
-#define                     nTRR1  0x0       
 #define                      TRR2  0x4        /* Mailbox 2 Transmit Request Reset */
-#define                     nTRR2  0x0       
 #define                      TRR3  0x8        /* Mailbox 3 Transmit Request Reset */
-#define                     nTRR3  0x0       
 #define                      TRR4  0x10       /* Mailbox 4 Transmit Request Reset */
-#define                     nTRR4  0x0       
 #define                      TRR5  0x20       /* Mailbox 5 Transmit Request Reset */
-#define                     nTRR5  0x0       
 #define                      TRR6  0x40       /* Mailbox 6 Transmit Request Reset */
-#define                     nTRR6  0x0       
 #define                      TRR7  0x80       /* Mailbox 7 Transmit Request Reset */
-#define                     nTRR7  0x0       
 #define                      TRR8  0x100      /* Mailbox 8 Transmit Request Reset */
-#define                     nTRR8  0x0       
 #define                      TRR9  0x200      /* Mailbox 9 Transmit Request Reset */
-#define                     nTRR9  0x0       
 #define                     TRR10  0x400      /* Mailbox 10 Transmit Request Reset */
-#define                    nTRR10  0x0       
 #define                     TRR11  0x800      /* Mailbox 11 Transmit Request Reset */
-#define                    nTRR11  0x0       
 #define                     TRR12  0x1000     /* Mailbox 12 Transmit Request Reset */
-#define                    nTRR12  0x0       
 #define                     TRR13  0x2000     /* Mailbox 13 Transmit Request Reset */
-#define                    nTRR13  0x0       
 #define                     TRR14  0x4000     /* Mailbox 14 Transmit Request Reset */
-#define                    nTRR14  0x0       
 #define                     TRR15  0x8000     /* Mailbox 15 Transmit Request Reset */
-#define                    nTRR15  0x0       
 
 /* Bit masks for CAN0_TRR2 */
 
 #define                     TRR16  0x1        /* Mailbox 16 Transmit Request Reset */
-#define                    nTRR16  0x0       
 #define                     TRR17  0x2        /* Mailbox 17 Transmit Request Reset */
-#define                    nTRR17  0x0       
 #define                     TRR18  0x4        /* Mailbox 18 Transmit Request Reset */
-#define                    nTRR18  0x0       
 #define                     TRR19  0x8        /* Mailbox 19 Transmit Request Reset */
-#define                    nTRR19  0x0       
 #define                     TRR20  0x10       /* Mailbox 20 Transmit Request Reset */
-#define                    nTRR20  0x0       
 #define                     TRR21  0x20       /* Mailbox 21 Transmit Request Reset */
-#define                    nTRR21  0x0       
 #define                     TRR22  0x40       /* Mailbox 22 Transmit Request Reset */
-#define                    nTRR22  0x0       
 #define                     TRR23  0x80       /* Mailbox 23 Transmit Request Reset */
-#define                    nTRR23  0x0       
 #define                     TRR24  0x100      /* Mailbox 24 Transmit Request Reset */
-#define                    nTRR24  0x0       
 #define                     TRR25  0x200      /* Mailbox 25 Transmit Request Reset */
-#define                    nTRR25  0x0       
 #define                     TRR26  0x400      /* Mailbox 26 Transmit Request Reset */
-#define                    nTRR26  0x0       
 #define                     TRR27  0x800      /* Mailbox 27 Transmit Request Reset */
-#define                    nTRR27  0x0       
 #define                     TRR28  0x1000     /* Mailbox 28 Transmit Request Reset */
-#define                    nTRR28  0x0       
 #define                     TRR29  0x2000     /* Mailbox 29 Transmit Request Reset */
-#define                    nTRR29  0x0       
 #define                     TRR30  0x4000     /* Mailbox 30 Transmit Request Reset */
-#define                    nTRR30  0x0       
 #define                     TRR31  0x8000     /* Mailbox 31 Transmit Request Reset */
-#define                    nTRR31  0x0       
 
 /* Bit masks for CAN0_AA1 */
 
 #define                       AA0  0x1        /* Mailbox 0 Abort Acknowledge */
-#define                      nAA0  0x0       
 #define                       AA1  0x2        /* Mailbox 1 Abort Acknowledge */
-#define                      nAA1  0x0       
 #define                       AA2  0x4        /* Mailbox 2 Abort Acknowledge */
-#define                      nAA2  0x0       
 #define                       AA3  0x8        /* Mailbox 3 Abort Acknowledge */
-#define                      nAA3  0x0       
 #define                       AA4  0x10       /* Mailbox 4 Abort Acknowledge */
-#define                      nAA4  0x0       
 #define                       AA5  0x20       /* Mailbox 5 Abort Acknowledge */
-#define                      nAA5  0x0       
 #define                       AA6  0x40       /* Mailbox 6 Abort Acknowledge */
-#define                      nAA6  0x0       
 #define                       AA7  0x80       /* Mailbox 7 Abort Acknowledge */
-#define                      nAA7  0x0       
 #define                       AA8  0x100      /* Mailbox 8 Abort Acknowledge */
-#define                      nAA8  0x0       
 #define                       AA9  0x200      /* Mailbox 9 Abort Acknowledge */
-#define                      nAA9  0x0       
 #define                      AA10  0x400      /* Mailbox 10 Abort Acknowledge */
-#define                     nAA10  0x0       
 #define                      AA11  0x800      /* Mailbox 11 Abort Acknowledge */
-#define                     nAA11  0x0       
 #define                      AA12  0x1000     /* Mailbox 12 Abort Acknowledge */
-#define                     nAA12  0x0       
 #define                      AA13  0x2000     /* Mailbox 13 Abort Acknowledge */
-#define                     nAA13  0x0       
 #define                      AA14  0x4000     /* Mailbox 14 Abort Acknowledge */
-#define                     nAA14  0x0       
 #define                      AA15  0x8000     /* Mailbox 15 Abort Acknowledge */
-#define                     nAA15  0x0       
 
 /* Bit masks for CAN0_AA2 */
 
 #define                      AA16  0x1        /* Mailbox 16 Abort Acknowledge */
-#define                     nAA16  0x0       
 #define                      AA17  0x2        /* Mailbox 17 Abort Acknowledge */
-#define                     nAA17  0x0       
 #define                      AA18  0x4        /* Mailbox 18 Abort Acknowledge */
-#define                     nAA18  0x0       
 #define                      AA19  0x8        /* Mailbox 19 Abort Acknowledge */
-#define                     nAA19  0x0       
 #define                      AA20  0x10       /* Mailbox 20 Abort Acknowledge */
-#define                     nAA20  0x0       
 #define                      AA21  0x20       /* Mailbox 21 Abort Acknowledge */
-#define                     nAA21  0x0       
 #define                      AA22  0x40       /* Mailbox 22 Abort Acknowledge */
-#define                     nAA22  0x0       
 #define                      AA23  0x80       /* Mailbox 23 Abort Acknowledge */
-#define                     nAA23  0x0       
 #define                      AA24  0x100      /* Mailbox 24 Abort Acknowledge */
-#define                     nAA24  0x0       
 #define                      AA25  0x200      /* Mailbox 25 Abort Acknowledge */
-#define                     nAA25  0x0       
 #define                      AA26  0x400      /* Mailbox 26 Abort Acknowledge */
-#define                     nAA26  0x0       
 #define                      AA27  0x800      /* Mailbox 27 Abort Acknowledge */
-#define                     nAA27  0x0       
 #define                      AA28  0x1000     /* Mailbox 28 Abort Acknowledge */
-#define                     nAA28  0x0       
 #define                      AA29  0x2000     /* Mailbox 29 Abort Acknowledge */
-#define                     nAA29  0x0       
 #define                      AA30  0x4000     /* Mailbox 30 Abort Acknowledge */
-#define                     nAA30  0x0       
 #define                      AA31  0x8000     /* Mailbox 31 Abort Acknowledge */
-#define                     nAA31  0x0       
 
 /* Bit masks for CAN0_TA1 */
 
 #define                       TA0  0x1        /* Mailbox 0 Transmit Acknowledge */
-#define                      nTA0  0x0       
 #define                       TA1  0x2        /* Mailbox 1 Transmit Acknowledge */
-#define                      nTA1  0x0       
 #define                       TA2  0x4        /* Mailbox 2 Transmit Acknowledge */
-#define                      nTA2  0x0       
 #define                       TA3  0x8        /* Mailbox 3 Transmit Acknowledge */
-#define                      nTA3  0x0       
 #define                       TA4  0x10       /* Mailbox 4 Transmit Acknowledge */
-#define                      nTA4  0x0       
 #define                       TA5  0x20       /* Mailbox 5 Transmit Acknowledge */
-#define                      nTA5  0x0       
 #define                       TA6  0x40       /* Mailbox 6 Transmit Acknowledge */
-#define                      nTA6  0x0       
 #define                       TA7  0x80       /* Mailbox 7 Transmit Acknowledge */
-#define                      nTA7  0x0       
 #define                       TA8  0x100      /* Mailbox 8 Transmit Acknowledge */
-#define                      nTA8  0x0       
 #define                       TA9  0x200      /* Mailbox 9 Transmit Acknowledge */
-#define                      nTA9  0x0       
 #define                      TA10  0x400      /* Mailbox 10 Transmit Acknowledge */
-#define                     nTA10  0x0       
 #define                      TA11  0x800      /* Mailbox 11 Transmit Acknowledge */
-#define                     nTA11  0x0       
 #define                      TA12  0x1000     /* Mailbox 12 Transmit Acknowledge */
-#define                     nTA12  0x0       
 #define                      TA13  0x2000     /* Mailbox 13 Transmit Acknowledge */
-#define                     nTA13  0x0       
 #define                      TA14  0x4000     /* Mailbox 14 Transmit Acknowledge */
-#define                     nTA14  0x0       
 #define                      TA15  0x8000     /* Mailbox 15 Transmit Acknowledge */
-#define                     nTA15  0x0       
 
 /* Bit masks for CAN0_TA2 */
 
 #define                      TA16  0x1        /* Mailbox 16 Transmit Acknowledge */
-#define                     nTA16  0x0       
 #define                      TA17  0x2        /* Mailbox 17 Transmit Acknowledge */
-#define                     nTA17  0x0       
 #define                      TA18  0x4        /* Mailbox 18 Transmit Acknowledge */
-#define                     nTA18  0x0       
 #define                      TA19  0x8        /* Mailbox 19 Transmit Acknowledge */
-#define                     nTA19  0x0       
 #define                      TA20  0x10       /* Mailbox 20 Transmit Acknowledge */
-#define                     nTA20  0x0       
 #define                      TA21  0x20       /* Mailbox 21 Transmit Acknowledge */
-#define                     nTA21  0x0       
 #define                      TA22  0x40       /* Mailbox 22 Transmit Acknowledge */
-#define                     nTA22  0x0       
 #define                      TA23  0x80       /* Mailbox 23 Transmit Acknowledge */
-#define                     nTA23  0x0       
 #define                      TA24  0x100      /* Mailbox 24 Transmit Acknowledge */
-#define                     nTA24  0x0       
 #define                      TA25  0x200      /* Mailbox 25 Transmit Acknowledge */
-#define                     nTA25  0x0       
 #define                      TA26  0x400      /* Mailbox 26 Transmit Acknowledge */
-#define                     nTA26  0x0       
 #define                      TA27  0x800      /* Mailbox 27 Transmit Acknowledge */
-#define                     nTA27  0x0       
 #define                      TA28  0x1000     /* Mailbox 28 Transmit Acknowledge */
-#define                     nTA28  0x0       
 #define                      TA29  0x2000     /* Mailbox 29 Transmit Acknowledge */
-#define                     nTA29  0x0       
 #define                      TA30  0x4000     /* Mailbox 30 Transmit Acknowledge */
-#define                     nTA30  0x0       
 #define                      TA31  0x8000     /* Mailbox 31 Transmit Acknowledge */
-#define                     nTA31  0x0       
 
 /* Bit masks for CAN0_RFH1 */
 
 #define                      RFH0  0x1        /* Mailbox 0 Remote Frame Handling Enable */
-#define                     nRFH0  0x0       
 #define                      RFH1  0x2        /* Mailbox 1 Remote Frame Handling Enable */
-#define                     nRFH1  0x0       
 #define                      RFH2  0x4        /* Mailbox 2 Remote Frame Handling Enable */
-#define                     nRFH2  0x0       
 #define                      RFH3  0x8        /* Mailbox 3 Remote Frame Handling Enable */
-#define                     nRFH3  0x0       
 #define                      RFH4  0x10       /* Mailbox 4 Remote Frame Handling Enable */
-#define                     nRFH4  0x0       
 #define                      RFH5  0x20       /* Mailbox 5 Remote Frame Handling Enable */
-#define                     nRFH5  0x0       
 #define                      RFH6  0x40       /* Mailbox 6 Remote Frame Handling Enable */
-#define                     nRFH6  0x0       
 #define                      RFH7  0x80       /* Mailbox 7 Remote Frame Handling Enable */
-#define                     nRFH7  0x0       
 #define                      RFH8  0x100      /* Mailbox 8 Remote Frame Handling Enable */
-#define                     nRFH8  0x0       
 #define                      RFH9  0x200      /* Mailbox 9 Remote Frame Handling Enable */
-#define                     nRFH9  0x0       
 #define                     RFH10  0x400      /* Mailbox 10 Remote Frame Handling Enable */
-#define                    nRFH10  0x0       
 #define                     RFH11  0x800      /* Mailbox 11 Remote Frame Handling Enable */
-#define                    nRFH11  0x0       
 #define                     RFH12  0x1000     /* Mailbox 12 Remote Frame Handling Enable */
-#define                    nRFH12  0x0       
 #define                     RFH13  0x2000     /* Mailbox 13 Remote Frame Handling Enable */
-#define                    nRFH13  0x0       
 #define                     RFH14  0x4000     /* Mailbox 14 Remote Frame Handling Enable */
-#define                    nRFH14  0x0       
 #define                     RFH15  0x8000     /* Mailbox 15 Remote Frame Handling Enable */
-#define                    nRFH15  0x0       
 
 /* Bit masks for CAN0_RFH2 */
 
 #define                     RFH16  0x1        /* Mailbox 16 Remote Frame Handling Enable */
-#define                    nRFH16  0x0       
 #define                     RFH17  0x2        /* Mailbox 17 Remote Frame Handling Enable */
-#define                    nRFH17  0x0       
 #define                     RFH18  0x4        /* Mailbox 18 Remote Frame Handling Enable */
-#define                    nRFH18  0x0       
 #define                     RFH19  0x8        /* Mailbox 19 Remote Frame Handling Enable */
-#define                    nRFH19  0x0       
 #define                     RFH20  0x10       /* Mailbox 20 Remote Frame Handling Enable */
-#define                    nRFH20  0x0       
 #define                     RFH21  0x20       /* Mailbox 21 Remote Frame Handling Enable */
-#define                    nRFH21  0x0       
 #define                     RFH22  0x40       /* Mailbox 22 Remote Frame Handling Enable */
-#define                    nRFH22  0x0       
 #define                     RFH23  0x80       /* Mailbox 23 Remote Frame Handling Enable */
-#define                    nRFH23  0x0       
 #define                     RFH24  0x100      /* Mailbox 24 Remote Frame Handling Enable */
-#define                    nRFH24  0x0       
 #define                     RFH25  0x200      /* Mailbox 25 Remote Frame Handling Enable */
-#define                    nRFH25  0x0       
 #define                     RFH26  0x400      /* Mailbox 26 Remote Frame Handling Enable */
-#define                    nRFH26  0x0       
 #define                     RFH27  0x800      /* Mailbox 27 Remote Frame Handling Enable */
-#define                    nRFH27  0x0       
 #define                     RFH28  0x1000     /* Mailbox 28 Remote Frame Handling Enable */
-#define                    nRFH28  0x0       
 #define                     RFH29  0x2000     /* Mailbox 29 Remote Frame Handling Enable */
-#define                    nRFH29  0x0       
 #define                     RFH30  0x4000     /* Mailbox 30 Remote Frame Handling Enable */
-#define                    nRFH30  0x0       
 #define                     RFH31  0x8000     /* Mailbox 31 Remote Frame Handling Enable */
-#define                    nRFH31  0x0       
 
 /* Bit masks for CAN0_MBIM1 */
 
 #define                     MBIM0  0x1        /* Mailbox 0 Mailbox Interrupt Mask */
-#define                    nMBIM0  0x0       
 #define                     MBIM1  0x2        /* Mailbox 1 Mailbox Interrupt Mask */
-#define                    nMBIM1  0x0       
 #define                     MBIM2  0x4        /* Mailbox 2 Mailbox Interrupt Mask */
-#define                    nMBIM2  0x0       
 #define                     MBIM3  0x8        /* Mailbox 3 Mailbox Interrupt Mask */
-#define                    nMBIM3  0x0       
 #define                     MBIM4  0x10       /* Mailbox 4 Mailbox Interrupt Mask */
-#define                    nMBIM4  0x0       
 #define                     MBIM5  0x20       /* Mailbox 5 Mailbox Interrupt Mask */
-#define                    nMBIM5  0x0       
 #define                     MBIM6  0x40       /* Mailbox 6 Mailbox Interrupt Mask */
-#define                    nMBIM6  0x0       
 #define                     MBIM7  0x80       /* Mailbox 7 Mailbox Interrupt Mask */
-#define                    nMBIM7  0x0       
 #define                     MBIM8  0x100      /* Mailbox 8 Mailbox Interrupt Mask */
-#define                    nMBIM8  0x0       
 #define                     MBIM9  0x200      /* Mailbox 9 Mailbox Interrupt Mask */
-#define                    nMBIM9  0x0       
 #define                    MBIM10  0x400      /* Mailbox 10 Mailbox Interrupt Mask */
-#define                   nMBIM10  0x0       
 #define                    MBIM11  0x800      /* Mailbox 11 Mailbox Interrupt Mask */
-#define                   nMBIM11  0x0       
 #define                    MBIM12  0x1000     /* Mailbox 12 Mailbox Interrupt Mask */
-#define                   nMBIM12  0x0       
 #define                    MBIM13  0x2000     /* Mailbox 13 Mailbox Interrupt Mask */
-#define                   nMBIM13  0x0       
 #define                    MBIM14  0x4000     /* Mailbox 14 Mailbox Interrupt Mask */
-#define                   nMBIM14  0x0       
 #define                    MBIM15  0x8000     /* Mailbox 15 Mailbox Interrupt Mask */
-#define                   nMBIM15  0x0       
 
 /* Bit masks for CAN0_MBIM2 */
 
 #define                    MBIM16  0x1        /* Mailbox 16 Mailbox Interrupt Mask */
-#define                   nMBIM16  0x0       
 #define                    MBIM17  0x2        /* Mailbox 17 Mailbox Interrupt Mask */
-#define                   nMBIM17  0x0       
 #define                    MBIM18  0x4        /* Mailbox 18 Mailbox Interrupt Mask */
-#define                   nMBIM18  0x0       
 #define                    MBIM19  0x8        /* Mailbox 19 Mailbox Interrupt Mask */
-#define                   nMBIM19  0x0       
 #define                    MBIM20  0x10       /* Mailbox 20 Mailbox Interrupt Mask */
-#define                   nMBIM20  0x0       
 #define                    MBIM21  0x20       /* Mailbox 21 Mailbox Interrupt Mask */
-#define                   nMBIM21  0x0       
 #define                    MBIM22  0x40       /* Mailbox 22 Mailbox Interrupt Mask */
-#define                   nMBIM22  0x0       
 #define                    MBIM23  0x80       /* Mailbox 23 Mailbox Interrupt Mask */
-#define                   nMBIM23  0x0       
 #define                    MBIM24  0x100      /* Mailbox 24 Mailbox Interrupt Mask */
-#define                   nMBIM24  0x0       
 #define                    MBIM25  0x200      /* Mailbox 25 Mailbox Interrupt Mask */
-#define                   nMBIM25  0x0       
 #define                    MBIM26  0x400      /* Mailbox 26 Mailbox Interrupt Mask */
-#define                   nMBIM26  0x0       
 #define                    MBIM27  0x800      /* Mailbox 27 Mailbox Interrupt Mask */
-#define                   nMBIM27  0x0       
 #define                    MBIM28  0x1000     /* Mailbox 28 Mailbox Interrupt Mask */
-#define                   nMBIM28  0x0       
 #define                    MBIM29  0x2000     /* Mailbox 29 Mailbox Interrupt Mask */
-#define                   nMBIM29  0x0       
 #define                    MBIM30  0x4000     /* Mailbox 30 Mailbox Interrupt Mask */
-#define                   nMBIM30  0x0       
 #define                    MBIM31  0x8000     /* Mailbox 31 Mailbox Interrupt Mask */
-#define                   nMBIM31  0x0       
 
 /* Bit masks for CAN0_MBTIF1 */
 
 #define                    MBTIF0  0x1        /* Mailbox 0 Mailbox Transmit Interrupt Flag */
-#define                   nMBTIF0  0x0       
 #define                    MBTIF1  0x2        /* Mailbox 1 Mailbox Transmit Interrupt Flag */
-#define                   nMBTIF1  0x0       
 #define                    MBTIF2  0x4        /* Mailbox 2 Mailbox Transmit Interrupt Flag */
-#define                   nMBTIF2  0x0       
 #define                    MBTIF3  0x8        /* Mailbox 3 Mailbox Transmit Interrupt Flag */
-#define                   nMBTIF3  0x0       
 #define                    MBTIF4  0x10       /* Mailbox 4 Mailbox Transmit Interrupt Flag */
-#define                   nMBTIF4  0x0       
 #define                    MBTIF5  0x20       /* Mailbox 5 Mailbox Transmit Interrupt Flag */
-#define                   nMBTIF5  0x0       
 #define                    MBTIF6  0x40       /* Mailbox 6 Mailbox Transmit Interrupt Flag */
-#define                   nMBTIF6  0x0       
 #define                    MBTIF7  0x80       /* Mailbox 7 Mailbox Transmit Interrupt Flag */
-#define                   nMBTIF7  0x0       
 #define                    MBTIF8  0x100      /* Mailbox 8 Mailbox Transmit Interrupt Flag */
-#define                   nMBTIF8  0x0       
 #define                    MBTIF9  0x200      /* Mailbox 9 Mailbox Transmit Interrupt Flag */
-#define                   nMBTIF9  0x0       
 #define                   MBTIF10  0x400      /* Mailbox 10 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF10  0x0       
 #define                   MBTIF11  0x800      /* Mailbox 11 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF11  0x0       
 #define                   MBTIF12  0x1000     /* Mailbox 12 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF12  0x0       
 #define                   MBTIF13  0x2000     /* Mailbox 13 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF13  0x0       
 #define                   MBTIF14  0x4000     /* Mailbox 14 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF14  0x0       
 #define                   MBTIF15  0x8000     /* Mailbox 15 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF15  0x0       
 
 /* Bit masks for CAN0_MBTIF2 */
 
 #define                   MBTIF16  0x1        /* Mailbox 16 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF16  0x0       
 #define                   MBTIF17  0x2        /* Mailbox 17 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF17  0x0       
 #define                   MBTIF18  0x4        /* Mailbox 18 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF18  0x0       
 #define                   MBTIF19  0x8        /* Mailbox 19 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF19  0x0       
 #define                   MBTIF20  0x10       /* Mailbox 20 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF20  0x0       
 #define                   MBTIF21  0x20       /* Mailbox 21 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF21  0x0       
 #define                   MBTIF22  0x40       /* Mailbox 22 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF22  0x0       
 #define                   MBTIF23  0x80       /* Mailbox 23 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF23  0x0       
 #define                   MBTIF24  0x100      /* Mailbox 24 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF24  0x0       
 #define                   MBTIF25  0x200      /* Mailbox 25 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF25  0x0       
 #define                   MBTIF26  0x400      /* Mailbox 26 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF26  0x0       
 #define                   MBTIF27  0x800      /* Mailbox 27 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF27  0x0       
 #define                   MBTIF28  0x1000     /* Mailbox 28 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF28  0x0       
 #define                   MBTIF29  0x2000     /* Mailbox 29 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF29  0x0       
 #define                   MBTIF30  0x4000     /* Mailbox 30 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF30  0x0       
 #define                   MBTIF31  0x8000     /* Mailbox 31 Mailbox Transmit Interrupt Flag */
-#define                  nMBTIF31  0x0       
 
 /* Bit masks for CAN0_MBRIF1 */
 
 #define                    MBRIF0  0x1        /* Mailbox 0 Mailbox Receive Interrupt Flag */
-#define                   nMBRIF0  0x0       
 #define                    MBRIF1  0x2        /* Mailbox 1 Mailbox Receive Interrupt Flag */
-#define                   nMBRIF1  0x0       
 #define                    MBRIF2  0x4        /* Mailbox 2 Mailbox Receive Interrupt Flag */
-#define                   nMBRIF2  0x0       
 #define                    MBRIF3  0x8        /* Mailbox 3 Mailbox Receive Interrupt Flag */
-#define                   nMBRIF3  0x0       
 #define                    MBRIF4  0x10       /* Mailbox 4 Mailbox Receive Interrupt Flag */
-#define                   nMBRIF4  0x0       
 #define                    MBRIF5  0x20       /* Mailbox 5 Mailbox Receive Interrupt Flag */
-#define                   nMBRIF5  0x0       
 #define                    MBRIF6  0x40       /* Mailbox 6 Mailbox Receive Interrupt Flag */
-#define                   nMBRIF6  0x0       
 #define                    MBRIF7  0x80       /* Mailbox 7 Mailbox Receive Interrupt Flag */
-#define                   nMBRIF7  0x0       
 #define                    MBRIF8  0x100      /* Mailbox 8 Mailbox Receive Interrupt Flag */
-#define                   nMBRIF8  0x0       
 #define                    MBRIF9  0x200      /* Mailbox 9 Mailbox Receive Interrupt Flag */
-#define                   nMBRIF9  0x0       
 #define                   MBRIF10  0x400      /* Mailbox 10 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF10  0x0       
 #define                   MBRIF11  0x800      /* Mailbox 11 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF11  0x0       
 #define                   MBRIF12  0x1000     /* Mailbox 12 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF12  0x0       
 #define                   MBRIF13  0x2000     /* Mailbox 13 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF13  0x0       
 #define                   MBRIF14  0x4000     /* Mailbox 14 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF14  0x0       
 #define                   MBRIF15  0x8000     /* Mailbox 15 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF15  0x0       
 
 /* Bit masks for CAN0_MBRIF2 */
 
 #define                   MBRIF16  0x1        /* Mailbox 16 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF16  0x0       
 #define                   MBRIF17  0x2        /* Mailbox 17 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF17  0x0       
 #define                   MBRIF18  0x4        /* Mailbox 18 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF18  0x0       
 #define                   MBRIF19  0x8        /* Mailbox 19 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF19  0x0       
 #define                   MBRIF20  0x10       /* Mailbox 20 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF20  0x0       
 #define                   MBRIF21  0x20       /* Mailbox 21 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF21  0x0       
 #define                   MBRIF22  0x40       /* Mailbox 22 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF22  0x0       
 #define                   MBRIF23  0x80       /* Mailbox 23 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF23  0x0       
 #define                   MBRIF24  0x100      /* Mailbox 24 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF24  0x0       
 #define                   MBRIF25  0x200      /* Mailbox 25 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF25  0x0       
 #define                   MBRIF26  0x400      /* Mailbox 26 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF26  0x0       
 #define                   MBRIF27  0x800      /* Mailbox 27 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF27  0x0       
 #define                   MBRIF28  0x1000     /* Mailbox 28 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF28  0x0       
 #define                   MBRIF29  0x2000     /* Mailbox 29 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF29  0x0       
 #define                   MBRIF30  0x4000     /* Mailbox 30 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF30  0x0       
 #define                   MBRIF31  0x8000     /* Mailbox 31 Mailbox Receive Interrupt Flag */
-#define                  nMBRIF31  0x0       
 
 /* Bit masks for EPPIx_STATUS */
 
 #define                 CFIFO_ERR  0x1        /* Chroma FIFO Error */
-#define                nCFIFO_ERR  0x0       
 #define                 YFIFO_ERR  0x2        /* Luma FIFO Error */
-#define                nYFIFO_ERR  0x0       
 #define                 LTERR_OVR  0x4        /* Line Track Overflow */
-#define                nLTERR_OVR  0x0       
 #define                LTERR_UNDR  0x8        /* Line Track Underflow */
-#define               nLTERR_UNDR  0x0       
 #define                 FTERR_OVR  0x10       /* Frame Track Overflow */
-#define                nFTERR_OVR  0x0       
 #define                FTERR_UNDR  0x20       /* Frame Track Underflow */
-#define               nFTERR_UNDR  0x0       
 #define                  ERR_NCOR  0x40       /* Preamble Error Not Corrected */
-#define                 nERR_NCOR  0x0       
 #define                   DMA1URQ  0x80       /* DMA1 Urgent Request */
-#define                  nDMA1URQ  0x0       
 #define                   DMA0URQ  0x100      /* DMA0 Urgent Request */
-#define                  nDMA0URQ  0x0       
 #define                   ERR_DET  0x4000     /* Preamble Error Detected */
-#define                  nERR_DET  0x0       
 #define                       FLD  0x8000     /* Field */
-#define                      nFLD  0x0       
 
 /* Bit masks for EPPIx_CONTROL */
 
 #define                   EPPI_EN  0x1        /* Enable */
-#define                  nEPPI_EN  0x0       
 #define                  EPPI_DIR  0x2        /* Direction */
-#define                 nEPPI_DIR  0x0       
 #define                  XFR_TYPE  0xc        /* Operating Mode */
 #define                    FS_CFG  0x30       /* Frame Sync Configuration */
 #define                   FLD_SEL  0x40       /* Field Select/Trigger */
-#define                  nFLD_SEL  0x0       
 #define                  ITU_TYPE  0x80       /* ITU Interlaced or Progressive */
-#define                 nITU_TYPE  0x0       
 #define                  BLANKGEN  0x100      /* ITU Output Mode with Internal Blanking Generation */
-#define                 nBLANKGEN  0x0       
 #define                   ICLKGEN  0x200      /* Internal Clock Generation */
-#define                  nICLKGEN  0x0       
 #define                    IFSGEN  0x400      /* Internal Frame Sync Generation */
-#define                   nIFSGEN  0x0       
 #define                      POLC  0x1800     /* Frame Sync and Data Driving/Sampling Edges */
 #define                      POLS  0x6000     /* Frame Sync Polarity */
 #define                   DLENGTH  0x38000    /* Data Length */
 #define                   SKIP_EN  0x40000    /* Skip Enable */
-#define                  nSKIP_EN  0x0       
 #define                   SKIP_EO  0x80000    /* Skip Even or Odd */
-#define                  nSKIP_EO  0x0       
 #define                    PACKEN  0x100000   /* Packing/Unpacking Enable */
-#define                   nPACKEN  0x0       
 #define                    SWAPEN  0x200000   /* Swap Enable */
-#define                   nSWAPEN  0x0       
 #define                  SIGN_EXT  0x400000   /* Sign Extension or Zero-filled / Data Split Format */
-#define                 nSIGN_EXT  0x0       
 #define             SPLT_EVEN_ODD  0x800000   /* Split Even and Odd Data Samples */
-#define            nSPLT_EVEN_ODD  0x0       
 #define               SUBSPLT_ODD  0x1000000  /* Sub-split Odd Samples */
-#define              nSUBSPLT_ODD  0x0       
 #define                    DMACFG  0x2000000  /* One or Two DMA Channels Mode */
-#define                   nDMACFG  0x0       
 #define                RGB_FMT_EN  0x4000000  /* RGB Formatting Enable */
-#define               nRGB_FMT_EN  0x0       
 #define                  FIFO_RWM  0x18000000 /* FIFO Regular Watermarks */
 #define                  FIFO_UWM  0x60000000 /* FIFO Urgent Watermarks */
 
+#define DLEN_8         (0 << 15) /* 000 - 8 bits */
+#define DLEN_10                (1 << 15) /* 001 - 10 bits */
+#define DLEN_12                (2 << 15) /* 010 - 12 bits */
+#define DLEN_14                (3 << 15) /* 011 - 14 bits */
+#define DLEN_16                (4 << 15) /* 100 - 16 bits */
+#define DLEN_18                (5 << 15) /* 101 - 18 bits */
+#define DLEN_24                (6 << 15) /* 110 - 24 bits */
+
+
 /* Bit masks for EPPIx_FS2W_LVB */
 
 #define                   F1VB_BD  0xff       /* Vertical Blanking before Field 1 Active Data */
 /* Bit masks for SPIx_CTL */
 
 #define                       SPE  0x4000     /* SPI Enable */
-#define                      nSPE  0x0       
 #define                       WOM  0x2000     /* Write Open Drain Master */
-#define                      nWOM  0x0       
 #define                      MSTR  0x1000     /* Master Mode */
-#define                     nMSTR  0x0       
 #define                      CPOL  0x800      /* Clock Polarity */
-#define                     nCPOL  0x0       
 #define                      CPHA  0x400      /* Clock Phase */
-#define                     nCPHA  0x0       
 #define                      LSBF  0x200      /* LSB First */
-#define                     nLSBF  0x0       
 #define                      SIZE  0x100      /* Size of Words */
-#define                     nSIZE  0x0       
 #define                     EMISO  0x20       /* Enable MISO Output */
-#define                    nEMISO  0x0       
 #define                      PSSE  0x10       /* Slave-Select Enable */
-#define                     nPSSE  0x0       
 #define                        GM  0x8        /* Get More Data */
-#define                       nGM  0x0       
 #define                        SZ  0x4        /* Send Zero */
-#define                       nSZ  0x0       
 #define                     TIMOD  0x3        /* Transfer Initiation Mode */
 
 /* Bit masks for SPIx_FLG */
 
 #define                      FLS1  0x2        /* Slave Select Enable 1 */
-#define                     nFLS1  0x0       
 #define                      FLS2  0x4        /* Slave Select Enable 2 */
-#define                     nFLS2  0x0       
 #define                      FLS3  0x8        /* Slave Select Enable 3 */
-#define                     nFLS3  0x0       
 #define                      FLG1  0x200      /* Slave Select Value 1 */
-#define                     nFLG1  0x0       
 #define                      FLG2  0x400      /* Slave Select Value 2 */
-#define                     nFLG2  0x0       
 #define                      FLG3  0x800      /* Slave Select Value 3 */
-#define                     nFLG3  0x0       
 
 /* Bit masks for SPIx_STAT */
 
 #define                     TXCOL  0x40       /* Transmit Collision Error */
-#define                    nTXCOL  0x0       
 #define                       RXS  0x20       /* RDBR Data Buffer Status */
-#define                      nRXS  0x0       
 #define                      RBSY  0x10       /* Receive Error */
-#define                     nRBSY  0x0       
 #define                       TXS  0x8        /* TDBR Data Buffer Status */
-#define                      nTXS  0x0       
 #define                       TXE  0x4        /* Transmission Error */
-#define                      nTXE  0x0       
 #define                      MODF  0x2        /* Mode Fault Error */
-#define                     nMODF  0x0       
 #define                      SPIF  0x1        /* SPI Finished */
-#define                     nSPIF  0x0       
 
 /* Bit masks for SPIx_TDBR */
 
 
 #define                  PRESCALE  0x7f       /* Prescale Value */
 #define                   TWI_ENA  0x80       /* TWI Enable */
-#define                  nTWI_ENA  0x0       
 #define                      SCCB  0x200      /* Serial Camera Control Bus */
-#define                     nSCCB  0x0       
 
 /* Bit maskes for TWIx_CLKDIV */
 
 /* Bit maskes for TWIx_SLAVE_CTL */
 
 #define                       SEN  0x1        /* Slave Enable */
-#define                      nSEN  0x0       
 #define                    STDVAL  0x4        /* Slave Transmit Data Valid */
-#define                   nSTDVAL  0x0       
 #define                       NAK  0x8        /* Not Acknowledge */
-#define                      nNAK  0x0       
 #define                       GEN  0x10       /* General Call Enable */
-#define                      nGEN  0x0       
 
 /* Bit maskes for TWIx_SLAVE_ADDR */
 
 /* Bit maskes for TWIx_SLAVE_STAT */
 
 #define                      SDIR  0x1        /* Slave Transfer Direction */
-#define                     nSDIR  0x0       
 #define                     GCALL  0x2        /* General Call */
-#define                    nGCALL  0x0       
 
 /* Bit maskes for TWIx_MASTER_CTL */
 
 #define                       MEN  0x1        /* Master Mode Enable */
-#define                      nMEN  0x0       
 #define                      MDIR  0x4        /* Master Transfer Direction */
-#define                     nMDIR  0x0       
 #define                      FAST  0x8        /* Fast Mode */
-#define                     nFAST  0x0       
 #define                      STOP  0x10       /* Issue Stop Condition */
-#define                     nSTOP  0x0       
 #define                    RSTART  0x20       /* Repeat Start */
-#define                   nRSTART  0x0       
 #define                      DCNT  0x3fc0     /* Data Transfer Count */
 #define                    SDAOVR  0x4000     /* Serial Data Override */
-#define                   nSDAOVR  0x0       
 #define                    SCLOVR  0x8000     /* Serial Clock Override */
-#define                   nSCLOVR  0x0       
 
 /* Bit maskes for TWIx_MASTER_ADDR */
 
 /* Bit maskes for TWIx_MASTER_STAT */
 
 #define                     MPROG  0x1        /* Master Transfer in Progress */
-#define                    nMPROG  0x0       
 #define                   LOSTARB  0x2        /* Lost Arbitration */
-#define                  nLOSTARB  0x0       
 #define                      ANAK  0x4        /* Address Not Acknowledged */
-#define                     nANAK  0x0       
 #define                      DNAK  0x8        /* Data Not Acknowledged */
-#define                     nDNAK  0x0       
 #define                  BUFRDERR  0x10       /* Buffer Read Error */
-#define                 nBUFRDERR  0x0       
 #define                  BUFWRERR  0x20       /* Buffer Write Error */
-#define                 nBUFWRERR  0x0       
 #define                    SDASEN  0x40       /* Serial Data Sense */
-#define                   nSDASEN  0x0       
 #define                    SCLSEN  0x80       /* Serial Clock Sense */
-#define                   nSCLSEN  0x0       
 #define                   BUSBUSY  0x100      /* Bus Busy */
-#define                  nBUSBUSY  0x0       
 
 /* Bit maskes for TWIx_FIFO_CTL */
 
 #define                  XMTFLUSH  0x1        /* Transmit Buffer Flush */
-#define                 nXMTFLUSH  0x0       
 #define                  RCVFLUSH  0x2        /* Receive Buffer Flush */
-#define                 nRCVFLUSH  0x0       
 #define                 XMTINTLEN  0x4        /* Transmit Buffer Interrupt Length */
-#define                nXMTINTLEN  0x0       
 #define                 RCVINTLEN  0x8        /* Receive Buffer Interrupt Length */
-#define                nRCVINTLEN  0x0       
 
 /* Bit maskes for TWIx_FIFO_STAT */
 
 /* Bit maskes for TWIx_INT_MASK */
 
 #define                    SINITM  0x1        /* Slave Transfer Initiated Interrupt Mask */
-#define                   nSINITM  0x0       
 #define                    SCOMPM  0x2        /* Slave Transfer Complete Interrupt Mask */
-#define                   nSCOMPM  0x0       
 #define                     SERRM  0x4        /* Slave Transfer Error Interrupt Mask */
-#define                    nSERRM  0x0       
 #define                     SOVFM  0x8        /* Slave Overflow Interrupt Mask */
-#define                    nSOVFM  0x0       
 #define                    MCOMPM  0x10       /* Master Transfer Complete Interrupt Mask */
-#define                   nMCOMPM  0x0       
 #define                     MERRM  0x20       /* Master Transfer Error Interrupt Mask */
-#define                    nMERRM  0x0       
 #define                  XMTSERVM  0x40       /* Transmit FIFO Service Interrupt Mask */
-#define                 nXMTSERVM  0x0       
 #define                  RCVSERVM  0x80       /* Receive FIFO Service Interrupt Mask */
-#define                 nRCVSERVM  0x0       
 
 /* Bit maskes for TWIx_INT_STAT */
 
 #define                     SINIT  0x1        /* Slave Transfer Initiated */
-#define                    nSINIT  0x0       
 #define                     SCOMP  0x2        /* Slave Transfer Complete */
-#define                    nSCOMP  0x0       
 #define                      SERR  0x4        /* Slave Transfer Error */
-#define                     nSERR  0x0       
 #define                      SOVF  0x8        /* Slave Overflow */
-#define                     nSOVF  0x0       
 #define                     MCOMP  0x10       /* Master Transfer Complete */
-#define                    nMCOMP  0x0       
 #define                      MERR  0x20       /* Master Transfer Error */
-#define                     nMERR  0x0       
 #define                   XMTSERV  0x40       /* Transmit FIFO Service */
-#define                  nXMTSERV  0x0       
 #define                   RCVSERV  0x80       /* Receive FIFO Service */
-#define                  nRCVSERV  0x0       
 
 /* Bit maskes for TWIx_XMT_DATA8 */
 
 /* Bit masks for SPORTx_TCR1 */
 
 #define                     TCKFE  0x4000     /* Clock Falling Edge Select */
-#define                    nTCKFE  0x0       
 #define                     LATFS  0x2000     /* Late Transmit Frame Sync */
-#define                    nLATFS  0x0       
 #define                      LTFS  0x1000     /* Low Transmit Frame Sync Select */
-#define                     nLTFS  0x0       
 #define                     DITFS  0x800      /* Data-Independent Transmit Frame Sync Select */
-#define                    nDITFS  0x0       
 #define                      TFSR  0x400      /* Transmit Frame Sync Required Select */
-#define                     nTFSR  0x0       
 #define                      ITFS  0x200      /* Internal Transmit Frame Sync Select */
-#define                     nITFS  0x0       
 #define                    TLSBIT  0x10       /* Transmit Bit Order */
-#define                   nTLSBIT  0x0       
 #define                    TDTYPE  0xc        /* Data Formatting Type Select */
 #define                     ITCLK  0x2        /* Internal Transmit Clock Select */
-#define                    nITCLK  0x0       
 #define                     TSPEN  0x1        /* Transmit Enable */
-#define                    nTSPEN  0x0       
 
 /* Bit masks for SPORTx_TCR2 */
 
 #define                     TRFST  0x400      /* Left/Right Order */
-#define                    nTRFST  0x0       
 #define                     TSFSE  0x200      /* Transmit Stereo Frame Sync Enable */
-#define                    nTSFSE  0x0       
 #define                      TXSE  0x100      /* TxSEC Enable */
-#define                     nTXSE  0x0       
 #define                    SLEN_T  0x1f       /* SPORT Word Length */
 
 /* Bit masks for SPORTx_RCR1 */
 
 #define                     RCKFE  0x4000     /* Clock Falling Edge Select */
-#define                    nRCKFE  0x0       
 #define                     LARFS  0x2000     /* Late Receive Frame Sync */
-#define                    nLARFS  0x0       
 #define                      LRFS  0x1000     /* Low Receive Frame Sync Select */
-#define                     nLRFS  0x0       
 #define                      RFSR  0x400      /* Receive Frame Sync Required Select */
-#define                     nRFSR  0x0       
 #define                      IRFS  0x200      /* Internal Receive Frame Sync Select */
-#define                     nIRFS  0x0       
 #define                    RLSBIT  0x10       /* Receive Bit Order */
-#define                   nRLSBIT  0x0       
 #define                    RDTYPE  0xc        /* Data Formatting Type Select */
 #define                     IRCLK  0x2        /* Internal Receive Clock Select */
-#define                    nIRCLK  0x0       
 #define                     RSPEN  0x1        /* Receive Enable */
-#define                    nRSPEN  0x0       
 
 /* Bit masks for SPORTx_RCR2 */
 
 #define                     RRFST  0x400      /* Left/Right Order */
-#define                    nRRFST  0x0       
 #define                     RSFSE  0x200      /* Receive Stereo Frame Sync Enable */
-#define                    nRSFSE  0x0       
 #define                      RXSE  0x100      /* RxSEC Enable */
-#define                     nRXSE  0x0       
 #define                    SLEN_R  0x1f       /* SPORT Word Length */
 
 /* Bit masks for SPORTx_STAT */
 
 #define                     TXHRE  0x40       /* Transmit Hold Register Empty */
-#define                    nTXHRE  0x0       
 #define                      TOVF  0x20       /* Sticky Transmit Overflow Status */
-#define                     nTOVF  0x0       
 #define                      TUVF  0x10       /* Sticky Transmit Underflow Status */
-#define                     nTUVF  0x0       
 #define                       TXF  0x8        /* Transmit FIFO Full Status */
-#define                      nTXF  0x0       
 #define                      ROVF  0x4        /* Sticky Receive Overflow Status */
-#define                     nROVF  0x0       
 #define                      RUVF  0x2        /* Sticky Receive Underflow Status */
-#define                     nRUVF  0x0       
 #define                      RXNE  0x1        /* Receive FIFO Not Empty Status */
-#define                     nRXNE  0x0       
 
 /* Bit masks for SPORTx_MCMC1 */
 
 
 #define                       MFD  0xf000     /* Multi channel Frame Delay */
 #define                      FSDR  0x80       /* Frame Sync to Data Relationship */
-#define                     nFSDR  0x0       
 #define                     MCMEM  0x10       /* Multi channel Frame Mode Enable */
-#define                    nMCMEM  0x0       
 #define                   MCDRXPE  0x8        /* Multi channel DMA Receive Packing */
-#define                  nMCDRXPE  0x0       
 #define                   MCDTXPE  0x4        /* Multi channel DMA Transmit Packing */
-#define                  nMCDTXPE  0x0       
 #define                     MCCRM  0x3        /* 2X Clock Recovery Mode */
 
 /* Bit masks for SPORTx_CHNL */
 #define                       WLS  0x3        /* Word Length Select */
 #endif
 #define                       STB  0x4        /* Stop Bits */
-#define                      nSTB  0x0       
 #define                       PEN  0x8        /* Parity Enable */
-#define                      nPEN  0x0       
 #define                       EPS  0x10       /* Even Parity Select */
-#define                      nEPS  0x0       
 #define                       STP  0x20       /* Sticky Parity */
-#define                      nSTP  0x0       
 #define                        SB  0x40       /* Set Break */
-#define                       nSB  0x0       
 
 /* Bit masks for UARTx_MCR */
 
 #define                      XOFF  0x1        /* Transmitter Off */
-#define                     nXOFF  0x0       
 #define                      MRTS  0x2        /* Manual Request To Send */
-#define                     nMRTS  0x0       
 #define                      RFIT  0x4        /* Receive FIFO IRQ Threshold */
-#define                     nRFIT  0x0       
 #define                      RFRT  0x8        /* Receive FIFO RTS Threshold */
-#define                     nRFRT  0x0       
 #define                  LOOP_ENA  0x10       /* Loopback Mode Enable */
-#define                 nLOOP_ENA  0x0       
 #define                     FCPOL  0x20       /* Flow Control Pin Polarity */
-#define                    nFCPOL  0x0       
 #define                      ARTS  0x40       /* Automatic Request To Send */
-#define                     nARTS  0x0       
 #define                      ACTS  0x80       /* Automatic Clear To Send */
-#define                     nACTS  0x0       
 
 /* Bit masks for UARTx_LSR */
 
 #define                        DR  0x1        /* Data Ready */
-#define                       nDR  0x0       
 #define                        OE  0x2        /* Overrun Error */
-#define                       nOE  0x0       
 #define                        PE  0x4        /* Parity Error */
-#define                       nPE  0x0       
 #define                        FE  0x8        /* Framing Error */
-#define                       nFE  0x0       
 #define                        BI  0x10       /* Break Interrupt */
-#define                       nBI  0x0       
 #define                      THRE  0x20       /* THR Empty */
-#define                     nTHRE  0x0       
 #define                      TEMT  0x40       /* Transmitter Empty */
-#define                     nTEMT  0x0       
 #define                       TFI  0x80       /* Transmission Finished Indicator */
-#define                      nTFI  0x0       
 
 /* Bit masks for UARTx_MSR */
 
 #define                      SCTS  0x1        /* Sticky CTS */
-#define                     nSCTS  0x0       
 #define                       CTS  0x10       /* Clear To Send */
-#define                      nCTS  0x0       
 #define                      RFCS  0x20       /* Receive FIFO Count Status */
-#define                     nRFCS  0x0       
-
-/* Bit masks for UARTx_IER_SET */
-
-#define                   ERBFI_S  0x1        /* Enable Receive Buffer Full Interrupt */
-#define                  nERBFI_S  0x0       
-#define                   ETBEI_S  0x2        /* Enable Transmit Buffer Empty Interrupt */
-#define                  nETBEI_S  0x0       
-#define                    ELSI_S  0x4        /* Enable Receive Status Interrupt */
-#define                   nELSI_S  0x0       
-#define                   EDSSI_S  0x8        /* Enable Modem Status Interrupt */
-#define                  nEDSSI_S  0x0       
-#define                  EDTPTI_S  0x10       /* Enable DMA Transmit PIRQ Interrupt */
-#define                 nEDTPTI_S  0x0       
-#define                    ETFI_S  0x20       /* Enable Transmission Finished Interrupt */
-#define                   nETFI_S  0x0       
-#define                   ERFCI_S  0x40       /* Enable Receive FIFO Count Interrupt */
-#define                  nERFCI_S  0x0       
-
-/* Bit masks for UARTx_IER_CLEAR */
-
-#define                   ERBFI_C  0x1        /* Enable Receive Buffer Full Interrupt */
-#define                  nERBFI_C  0x0       
-#define                   ETBEI_C  0x2        /* Enable Transmit Buffer Empty Interrupt */
-#define                  nETBEI_C  0x0       
-#define                    ELSI_C  0x4        /* Enable Receive Status Interrupt */
-#define                   nELSI_C  0x0       
-#define                   EDSSI_C  0x8        /* Enable Modem Status Interrupt */
-#define                  nEDSSI_C  0x0       
-#define                  EDTPTI_C  0x10       /* Enable DMA Transmit PIRQ Interrupt */
-#define                 nEDTPTI_C  0x0       
-#define                    ETFI_C  0x20       /* Enable Transmission Finished Interrupt */
-#define                   nETFI_C  0x0       
-#define                   ERFCI_C  0x40       /* Enable Receive FIFO Count Interrupt */
-#define                  nERFCI_C  0x0       
+
+/* Bit masks for UARTx_IER_SET & UARTx_IER_CLEAR */
+
+#define                   ERBFI  0x1        /* Enable Receive Buffer Full Interrupt */
+#define                   ETBEI  0x2        /* Enable Transmit Buffer Empty Interrupt */
+#define                    ELSI  0x4        /* Enable Receive Status Interrupt */
+#define                   EDSSI  0x8        /* Enable Modem Status Interrupt */
+#define                  EDTPTI  0x10       /* Enable DMA Transmit PIRQ Interrupt */
+#define                    ETFI  0x20       /* Enable Transmission Finished Interrupt */
+#define                   ERFCI  0x40       /* Enable Receive FIFO Count Interrupt */
 
 /* Bit masks for UARTx_GCTL */
 
 #define                      UCEN  0x1        /* UART Enable */
-#define                     nUCEN  0x0       
 #define                      IREN  0x2        /* IrDA Mode Enable */
-#define                     nIREN  0x0       
 #define                     TPOLC  0x4        /* IrDA TX Polarity Change */
-#define                    nTPOLC  0x0       
 #define                     RPOLC  0x8        /* IrDA RX Polarity Change */
-#define                    nRPOLC  0x0       
 #define                       FPE  0x10       /* Force Parity Error */
-#define                      nFPE  0x0       
 #define                       FFE  0x20       /* Force Framing Error */
-#define                      nFFE  0x0       
 #define                      EDBO  0x40       /* Enable Divide-by-One */
-#define                     nEDBO  0x0       
 #define                     EGLSI  0x80       /* Enable Global LS Interrupt */
-#define                    nEGLSI  0x0       
 
 
 /* ******************************************* */
 /* BCODE bit field options (SYSCFG register) */
 
 #define BCODE_WAKEUP    0x0000  /* boot according to wake-up condition */
-#define BCODE_FULLBOOT  0x0010  /* always perform full boot */ 
+#define BCODE_FULLBOOT  0x0010  /* always perform full boot */
 #define BCODE_QUICKBOOT 0x0020  /* always perform quick boot */
 #define BCODE_NOBOOT    0x0030  /* always perform full boot */
 
 /* CNT_COMMAND bit field options */
+
 #define W1LCNT_ZERO   0x0001   /* write 1 to load CNT_COUNTER with zero */
 #define W1LCNT_MIN    0x0004   /* write 1 to load CNT_COUNTER from CNT_MIN */
 #define W1LCNT_MAX    0x0008   /* write 1 to load CNT_COUNTER from CNT_MAX */
+
 #define W1LMIN_ZERO   0x0010   /* write 1 to load CNT_MIN with zero */
 #define W1LMIN_CNT    0x0020   /* write 1 to load CNT_MIN from CNT_COUNTER */
 #define W1LMIN_MAX    0x0080   /* write 1 to load CNT_MIN from CNT_MAX */
+
 #define W1LMAX_ZERO   0x0100   /* write 1 to load CNT_MAX with zero */
 #define W1LMAX_CNT    0x0200   /* write 1 to load CNT_MAX from CNT_COUNTER */
 #define W1LMAX_MIN    0x0400   /* write 1 to load CNT_MAX from CNT_MIN */
+
 /* CNT_CONFIG bit field options */
+
 #define CNTMODE_QUADENC  0x0000  /* quadrature encoder mode */
 #define CNTMODE_BINENC   0x0100  /* binary encoder mode */
 #define CNTMODE_UDCNT    0x0200  /* up/down counter mode */
 #define CNTMODE_DIRCNT   0x0400  /* direction counter mode */
 #define CNTMODE_DIRTMR   0x0500  /* direction timer mode */
+
 #define BNDMODE_COMP     0x0000  /* boundary compare mode */
 #define BNDMODE_ZERO     0x1000  /* boundary compare and zero mode */
 #define BNDMODE_CAPT     0x2000  /* boundary capture mode */
 #define EXT_CLK  0x0003
 
 /* UARTx_LCR bit field options */
+
 #define WLS_5   0x0000    /* 5 data bits */
 #define WLS_6   0x0001    /* 6 data bits */
 #define WLS_7   0x0002    /* 7 data bits */
 #define PIQ30 0x40000000
 #define PIQ31 0x80000000
 
-/* PORT A Bit Definitions for the registers 
+/* PORT A Bit Definitions for the registers
 PORTA, PORTA_SET, PORTA_CLEAR,
 PORTA_DIR_SET, PORTA_DIR_CLEAR, PORTA_INEN,
 PORTA_FER registers
@@ -4507,7 +3483,7 @@ PORTA_FER registers
 #define PA14 0x4000
 #define PA15 0x8000
 
-/* PORT B Bit Definitions for the registers 
+/* PORT B Bit Definitions for the registers
 PORTB, PORTB_SET, PORTB_CLEAR,
 PORTB_DIR_SET, PORTB_DIR_CLEAR, PORTB_INEN,
 PORTB_FER registers
@@ -4530,7 +3506,7 @@ PORTB_FER registers
 #define PB14 0x4000
 
 
-/* PORT C Bit Definitions for the registers 
+/* PORT C Bit Definitions for the registers
 PORTC, PORTC_SET, PORTC_CLEAR,
 PORTC_DIR_SET, PORTC_DIR_CLEAR, PORTC_INEN,
 PORTC_FER registers
@@ -4553,7 +3529,7 @@ PORTC_FER registers
 #define PC13 0x2000
 
 
-/* PORT D Bit Definitions for the registers 
+/* PORT D Bit Definitions for the registers
 PORTD, PORTD_SET, PORTD_CLEAR,
 PORTD_DIR_SET, PORTD_DIR_CLEAR, PORTD_INEN,
 PORTD_FER registers
@@ -4576,7 +3552,7 @@ PORTD_FER registers
 #define PD14 0x4000
 #define PD15 0x8000
 
-/* PORT E Bit Definitions for the registers 
+/* PORT E Bit Definitions for the registers
 PORTE, PORTE_SET, PORTE_CLEAR,
 PORTE_DIR_SET, PORTE_DIR_CLEAR, PORTE_INEN,
 PORTE_FER registers
@@ -4600,7 +3576,7 @@ PORTE_FER registers
 #define PE14 0x4000
 #define PE15 0x8000
 
-/* PORT F Bit Definitions for the registers 
+/* PORT F Bit Definitions for the registers
 PORTF, PORTF_SET, PORTF_CLEAR,
 PORTF_DIR_SET, PORTF_DIR_CLEAR, PORTF_INEN,
 PORTF_FER registers
@@ -4624,7 +3600,7 @@ PORTF_FER registers
 #define PF14 0x4000
 #define PF15 0x8000
 
-/* PORT G Bit Definitions for the registers 
+/* PORT G Bit Definitions for the registers
 PORTG, PORTG_SET, PORTG_CLEAR,
 PORTG_DIR_SET, PORTG_DIR_CLEAR, PORTG_INEN,
 PORTG_FER registers
@@ -4648,7 +3624,7 @@ PORTG_FER registers
 #define PG14 0x4000
 #define PG15 0x8000
 
-/* PORT H Bit Definitions for the registers 
+/* PORT H Bit Definitions for the registers
 PORTH, PORTH_SET, PORTH_CLEAR,
 PORTH_DIR_SET, PORTH_DIR_CLEAR, PORTH_INEN,
 PORTH_FER registers
@@ -4671,7 +3647,7 @@ PORTH_FER registers
 #define PH13 0x2000
 
 
-/* PORT I Bit Definitions for the registers 
+/* PORT I Bit Definitions for the registers
 PORTI, PORTI_SET, PORTI_CLEAR,
 PORTI_DIR_SET, PORTI_DIR_CLEAR, PORTI_INEN,
 PORTI_FER registers
@@ -4695,7 +3671,7 @@ PORTI_FER registers
 #define PI14 0x4000
 #define PI15 0x8000
 
-/* PORT J Bit Definitions for the registers 
+/* PORT J Bit Definitions for the registers
 PORTJ, PORTJ_SET, PORTJ_CLEAR,
 PORTJ_DIR_SET, PORTJ_DIR_CLEAR, PORTJ_INEN,
 PORTJ_FER registers
@@ -4716,7 +3692,7 @@ PORTJ_FER registers
 #define PJ11 0x0800
 #define PJ12 0x1000
 #define PJ13 0x2000
+
 
 /* Port Muxing Bit Fields for PORTx_MUX Registers */
 
@@ -4860,7 +3836,7 @@ PORTJ_FER registers
 #define B0MAP_PIL 0x00000006 /* Map Port I Low to Byte 0 */
 #define B0MAP_PJL 0x00000007 /* Map Port J Low to Byte 0 */
 
-#define B1MAP_PCH 0x00000000 /* Map Port C High to Byte 1 */ 
+#define B1MAP_PCH 0x00000000 /* Map Port C High to Byte 1 */
 #define B1MAP_PDH 0x00000100 /* Map Port D High to Byte 1 */
 #define B1MAP_PEH 0x00000200 /* Map Port E High to Byte 1 */
 #define B1MAP_PFH 0x00000300 /* Map Port F High to Byte 1 */
@@ -4869,27 +3845,27 @@ PORTJ_FER registers
 #define B1MAP_PIH 0x00000600 /* Map Port I High to Byte 1 */
 #define B1MAP_PJH 0x00000700 /* Map Port J High to Byte 1 */
 
-#define B2MAP_PCL 0x00000000 /* Map Port C Low to Byte 2 */ 
-#define B2MAP_PDL 0x00010000 /* Map Port D Low to Byte 2 */ 
-#define B2MAP_PEL 0x00020000 /* Map Port E Low to Byte 2 */ 
-#define B2MAP_PFL 0x00030000 /* Map Port F Low to Byte 2 */ 
-#define B2MAP_PGL 0x00040000 /* Map Port G Low to Byte 2 */ 
-#define B2MAP_PHL 0x00050000 /* Map Port H Low to Byte 2 */ 
-#define B2MAP_PIL 0x00060000 /* Map Port I Low to Byte 2 */ 
-#define B2MAP_PJL 0x00070000 /* Map Port J Low to Byte 2 */ 
-
-#define B3MAP_PCH 0x00000000 /* Map Port C High to Byte 3 */ 
-#define B3MAP_PDH 0x01000000 /* Map Port D High to Byte 3 */ 
-#define B3MAP_PEH 0x02000000 /* Map Port E High to Byte 3 */ 
-#define B3MAP_PFH 0x03000000 /* Map Port F High to Byte 3 */ 
-#define B3MAP_PGH 0x04000000 /* Map Port G High to Byte 3 */ 
-#define B3MAP_PHH 0x05000000 /* Map Port H High to Byte 3 */ 
-#define B3MAP_PIH 0x06000000 /* Map Port I High to Byte 3 */ 
-#define B3MAP_PJH 0x07000000 /* Map Port J High to Byte 3 */ 
+#define B2MAP_PCL 0x00000000 /* Map Port C Low to Byte 2 */
+#define B2MAP_PDL 0x00010000 /* Map Port D Low to Byte 2 */
+#define B2MAP_PEL 0x00020000 /* Map Port E Low to Byte 2 */
+#define B2MAP_PFL 0x00030000 /* Map Port F Low to Byte 2 */
+#define B2MAP_PGL 0x00040000 /* Map Port G Low to Byte 2 */
+#define B2MAP_PHL 0x00050000 /* Map Port H Low to Byte 2 */
+#define B2MAP_PIL 0x00060000 /* Map Port I Low to Byte 2 */
+#define B2MAP_PJL 0x00070000 /* Map Port J Low to Byte 2 */
+
+#define B3MAP_PCH 0x00000000 /* Map Port C High to Byte 3 */
+#define B3MAP_PDH 0x01000000 /* Map Port D High to Byte 3 */
+#define B3MAP_PEH 0x02000000 /* Map Port E High to Byte 3 */
+#define B3MAP_PFH 0x03000000 /* Map Port F High to Byte 3 */
+#define B3MAP_PGH 0x04000000 /* Map Port G High to Byte 3 */
+#define B3MAP_PHH 0x05000000 /* Map Port H High to Byte 3 */
+#define B3MAP_PIH 0x06000000 /* Map Port I High to Byte 3 */
+#define B3MAP_PJH 0x07000000 /* Map Port J High to Byte 3 */
 
 
 /* for legacy compatibility */
+
 #define WLS(x)  (((x)-5) & 0x03) /* Word Length Select */
 #define W1LMAX_MAX W1LMAX_MIN
 #define EBIU_AMCBCTL0 EBIU_AMBCTL0
diff --git a/include/asm-blackfin/mach-bf548/dma.h b/include/asm-blackfin/mach-bf548/dma.h
new file mode 100644 (file)
index 0000000..fcc8b4c
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * file:         include/asm-blackfin/mach-bf548/dma.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *     system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * 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, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _MACH_DMA_H_
+#define _MACH_DMA_H_
+
+#define CH_SPORT0_RX           0
+#define CH_SPORT0_TX           1
+#define CH_SPORT1_RX           2
+#define CH_SPORT1_TX           3
+#define CH_SPI0                        4
+#define CH_SPI1                        5
+#define CH_UART0_RX            6
+#define CH_UART0_TX            7
+#define CH_UART1_RX            8
+#define CH_UART1_TX            9
+#define CH_ATAPI_RX            10
+#define CH_ATAPI_TX            11
+#define CH_EPPI0               12
+#define CH_EPPI1               13
+#define CH_EPPI2               14
+#define CH_PIXC_IMAGE          15
+#define CH_PIXC_OVERLAY                16
+#define CH_PIXC_OUTPUT         17
+#define CH_SPORT2_RX           18
+#define CH_SPORT2_TX           19
+#define CH_SPORT3_RX           20
+#define CH_SPORT3_TX           21
+#define CH_SDH                 22
+#define CH_SPI2                        23
+
+#define CH_MEM_STREAM0_DEST    24
+#define CH_MEM_STREAM0_SRC     25
+#define CH_MEM_STREAM1_DEST    26
+#define CH_MEM_STREAM1_SRC     27
+#define CH_MEM_STREAM2_DEST    28
+#define CH_MEM_STREAM2_SRC     29
+#define CH_MEM_STREAM3_DEST    30
+#define CH_MEM_STREAM3_SRC     31
+
+#define MAX_BLACKFIN_DMA_CHANNEL 32
+
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+#endif
diff --git a/include/asm-blackfin/mach-bf548/gpio.h b/include/asm-blackfin/mach-bf548/gpio.h
new file mode 100644 (file)
index 0000000..dbf66bc
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/gpio.h
+ * Based on:
+ * Author:      Michael Hennerich (hennerich@blackfin.uclinux.org)
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2007 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
+ */
+
+
+
+#define GPIO_PA0       0
+#define GPIO_PA1       1
+#define GPIO_PA2       2
+#define GPIO_PA3       3
+#define GPIO_PA4       4
+#define GPIO_PA5       5
+#define GPIO_PA6       6
+#define GPIO_PA7       7
+#define GPIO_PA8       8
+#define GPIO_PA9       9
+#define GPIO_PA10      10
+#define GPIO_PA11      11
+#define GPIO_PA12      12
+#define GPIO_PA13      13
+#define GPIO_PA14      14
+#define GPIO_PA15      15
+#define GPIO_PB0       16
+#define GPIO_PB1       17
+#define GPIO_PB2       18
+#define GPIO_PB3       19
+#define GPIO_PB4       20
+#define GPIO_PB5       21
+#define GPIO_PB6       22
+#define GPIO_PB7       23
+#define GPIO_PB8       24
+#define GPIO_PB9       25
+#define GPIO_PB10      26
+#define GPIO_PB11      27
+#define GPIO_PB12      28
+#define GPIO_PB13      29
+#define GPIO_PB14      30
+#define GPIO_PB15      31      /* N/A */
+#define GPIO_PC0       32
+#define GPIO_PC1       33
+#define GPIO_PC2       34
+#define GPIO_PC3       35
+#define GPIO_PC4       36
+#define GPIO_PC5       37
+#define GPIO_PC6       38
+#define GPIO_PC7       39
+#define GPIO_PC8       40
+#define GPIO_PC9       41
+#define GPIO_PC10      42
+#define GPIO_PC11      43
+#define GPIO_PC12      44
+#define GPIO_PC13      45
+#define GPIO_PC14      46      /* N/A */
+#define GPIO_PC15      47      /* N/A */
+#define GPIO_PD0       48
+#define GPIO_PD1       49
+#define GPIO_PD2       50
+#define GPIO_PD3       51
+#define GPIO_PD4       52
+#define GPIO_PD5       53
+#define GPIO_PD6       54
+#define GPIO_PD7       55
+#define GPIO_PD8       56
+#define GPIO_PD9       57
+#define GPIO_PD10      58
+#define GPIO_PD11      59
+#define GPIO_PD12      60
+#define GPIO_PD13      61
+#define GPIO_PD14      62
+#define GPIO_PD15      63
+#define GPIO_PE0       64
+#define GPIO_PE1       65
+#define GPIO_PE2       66
+#define GPIO_PE3       67
+#define GPIO_PE4       68
+#define GPIO_PE5       69
+#define GPIO_PE6       70
+#define GPIO_PE7       71
+#define GPIO_PE8       72
+#define GPIO_PE9       73
+#define GPIO_PE10      74
+#define GPIO_PE11      75
+#define GPIO_PE12      76
+#define GPIO_PE13      77
+#define GPIO_PE14      78
+#define GPIO_PE15      79
+#define GPIO_PF0       80
+#define GPIO_PF1       81
+#define GPIO_PF2       82
+#define GPIO_PF3       83
+#define GPIO_PF4       84
+#define GPIO_PF5       85
+#define GPIO_PF6       86
+#define GPIO_PF7       87
+#define GPIO_PF8       88
+#define GPIO_PF9       89
+#define GPIO_PF10      90
+#define GPIO_PF11      91
+#define GPIO_PF12      92
+#define GPIO_PF13      93
+#define GPIO_PF14      94
+#define GPIO_PF15      95
+#define GPIO_PG0       96
+#define GPIO_PG1       97
+#define GPIO_PG2       98
+#define GPIO_PG3       99
+#define GPIO_PG4       100
+#define GPIO_PG5       101
+#define GPIO_PG6       102
+#define GPIO_PG7       103
+#define GPIO_PG8       104
+#define GPIO_PG9       105
+#define GPIO_PG10      106
+#define GPIO_PG11      107
+#define GPIO_PG12      108
+#define GPIO_PG13      109
+#define GPIO_PG14      110
+#define GPIO_PG15      111
+#define GPIO_PH0       112
+#define GPIO_PH1       113
+#define GPIO_PH2       114
+#define GPIO_PH3       115
+#define GPIO_PH4       116
+#define GPIO_PH5       117
+#define GPIO_PH6       118
+#define GPIO_PH7       119
+#define GPIO_PH8       120
+#define GPIO_PH9       121
+#define GPIO_PH10      122
+#define GPIO_PH11      123
+#define GPIO_PH12      124
+#define GPIO_PH13      125
+#define GPIO_PH14      126     /* N/A */
+#define GPIO_PH15      127     /* N/A */
+#define GPIO_PI0       128
+#define GPIO_PI1       129
+#define GPIO_PI2       130
+#define GPIO_PI3       131
+#define GPIO_PI4       132
+#define GPIO_PI5       133
+#define GPIO_PI6       134
+#define GPIO_PI7       135
+#define GPIO_PI8       136
+#define GPIO_PI9       137
+#define GPIO_PI10      138
+#define GPIO_PI11      139
+#define GPIO_PI12      140
+#define GPIO_PI13      141
+#define GPIO_PI14      142
+#define GPIO_PI15      143
+#define GPIO_PJ0       144
+#define GPIO_PJ1       145
+#define GPIO_PJ2       146
+#define GPIO_PJ3       147
+#define GPIO_PJ4       148
+#define GPIO_PJ5       149
+#define GPIO_PJ6       150
+#define GPIO_PJ7       151
+#define GPIO_PJ8       152
+#define GPIO_PJ9       153
+#define GPIO_PJ10      154
+#define GPIO_PJ11      155
+#define GPIO_PJ12      156
+#define GPIO_PJ13      157
+#define GPIO_PJ14      158     /* N/A */
+#define GPIO_PJ15      159     /* N/A */
+
+#define MAX_BLACKFIN_GPIOS 160
+
+struct gpio_port_t {
+       unsigned short port_fer;
+       unsigned short dummy1;
+       unsigned short port_data;
+       unsigned short dummy2;
+       unsigned short port_set;
+       unsigned short dummy3;
+       unsigned short port_clear;
+       unsigned short dummy4;
+       unsigned short port_dir_set;
+       unsigned short dummy5;
+       unsigned short port_dir_clear;
+       unsigned short dummy6;
+       unsigned short port_inen;
+       unsigned short dummy7;
+       unsigned int port_mux;
+};
+
+int gpio_request(unsigned short gpio, const char *label);
+void peripheral_free(unsigned short per);
+int peripheral_request_list(unsigned short per[], const char *label);
+void peripheral_free_list(unsigned short per[]);
diff --git a/include/asm-blackfin/mach-bf548/irq.h b/include/asm-blackfin/mach-bf548/irq.h
new file mode 100644 (file)
index 0000000..0b3325b
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * file:       include/asm-blackfin/mach-bf548/irq.h
+ * based on:   include/asm-blackfin/mach-bf537/irq.h
+ * author:     Roy Huang (roy.huang@analog.com)
+ *
+ * created:
+ * description:
+ *     system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * 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, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _BF548_IRQ_H_
+#define _BF548_IRQ_H_
+
+/*
+ * Interrupt source definitions
+            Event Source    Core Event Name
+Core        Emulation               **
+Events         (highest priority)  EMU         0
+            Reset                   RST         1
+            NMI                     NMI         2
+            Exception               EVX         3
+            Reserved                --          4
+            Hardware Error          IVHW        5
+            Core Timer              IVTMR       6 *
+
+.....
+
+            Software Interrupt 1    IVG14       31
+            Software Interrupt 2    --
+                 (lowest priority)  IVG15       32 *
+ */
+
+#define NR_PERI_INTS    (32 * 3)
+
+/* The ABSTRACT IRQ definitions */
+/** the first seven of the following are fixed, the rest you change if you need to **/
+#define IRQ_EMU                0       /* Emulation */
+#define IRQ_RST                1       /* reset */
+#define IRQ_NMI                2       /* Non Maskable */
+#define IRQ_EVX                3       /* Exception */
+#define IRQ_UNUSED     4       /* - unused interrupt*/
+#define IRQ_HWERR      5       /* Hardware Error */
+#define IRQ_CORETMR    6       /* Core timer */
+
+#define BFIN_IRQ(x)    ((x) + 7)
+
+#define IRQ_PLL_WAKEUP BFIN_IRQ(0)     /* PLL Wakeup Interrupt */
+#define IRQ_DMAC0_ERR  BFIN_IRQ(1)     /* DMAC0 Status Interrupt */
+#define IRQ_EPPI0_ERR  BFIN_IRQ(2)     /* EPPI0 Error Interrupt */
+#define IRQ_SPORT0_ERR BFIN_IRQ(3)     /* SPORT0 Error Interrupt */
+#define IRQ_SPORT1_ERR BFIN_IRQ(4)     /* SPORT1 Error Interrupt */
+#define IRQ_SPI0_ERR   BFIN_IRQ(5)     /* SPI0 Status(Error) Interrupt */
+#define IRQ_UART0_ERR  BFIN_IRQ(6)     /* UART0 Status(Error) Interrupt */
+#define IRQ_RTC                BFIN_IRQ(7)     /* RTC Interrupt */
+#define IRQ_EPPI0      BFIN_IRQ(8)     /* EPPI0 Interrupt (DMA12) */
+#define IRQ_SPORT0_RX  BFIN_IRQ(9)     /* SPORT0 RX Interrupt (DMA0) */
+#define IRQ_SPORT0_TX  BFIN_IRQ(10)    /* SPORT0 TX Interrupt (DMA1) */
+#define IRQ_SPORT1_RX  BFIN_IRQ(11)    /* SPORT1 RX Interrupt (DMA2) */
+#define IRQ_SPORT1_TX  BFIN_IRQ(12)    /* SPORT1 TX Interrupt (DMA3) */
+#define IRQ_SPI0       BFIN_IRQ(13)    /* SPI0 Interrupt (DMA4) */
+#define IRQ_UART0_RX   BFIN_IRQ(14)    /* UART0 RX Interrupt (DMA6) */
+#define IRQ_UART0_TX   BFIN_IRQ(15)    /* UART0 TX Interrupt (DMA7) */
+#define IRQ_TIMER8     BFIN_IRQ(16)    /* TIMER 8 Interrupt */
+#define IRQ_TIMER9     BFIN_IRQ(17)    /* TIMER 9 Interrupt */
+#define IRQ_TIMER10    BFIN_IRQ(18)    /* TIMER 10 Interrupt */
+#define IRQ_PINT0      BFIN_IRQ(19)    /* PINT0 Interrupt */
+#define IRQ_PINT1      BFIN_IRQ(20)    /* PINT1 Interrupt */
+#define IRQ_MDMAS0     BFIN_IRQ(21)    /* MDMA Stream 0 Interrupt */
+#define IRQ_MDMAS1     BFIN_IRQ(22)    /* MDMA Stream 1 Interrupt */
+#define IRQ_WATCHDOG   BFIN_IRQ(23)    /* Watchdog Interrupt */
+#define IRQ_DMAC1_ERR  BFIN_IRQ(24)    /* DMAC1 Status (Error) Interrupt */
+#define IRQ_SPORT2_ERR BFIN_IRQ(25)    /* SPORT2 Error Interrupt */
+#define IRQ_SPORT3_ERR BFIN_IRQ(26)    /* SPORT3 Error Interrupt */
+#define IRQ_MXVR_DATA  BFIN_IRQ(27)    /* MXVR Data Interrupt */
+#define IRQ_SPI1_ERR   BFIN_IRQ(28)    /* SPI1 Status (Error) Interrupt */
+#define IRQ_SPI2_ERR   BFIN_IRQ(29)    /* SPI2 Status (Error) Interrupt */
+#define IRQ_UART1_ERR  BFIN_IRQ(30)    /* UART1 Status (Error) Interrupt */
+#define IRQ_UART2_ERR  BFIN_IRQ(31)    /* UART2 Status (Error) Interrupt */
+#define IRQ_CAN0_ERR   BFIN_IRQ(32)    /* CAN0 Status (Error) Interrupt */
+#define IRQ_SPORT2_RX  BFIN_IRQ(33)    /* SPORT2 RX (DMA18) Interrupt */
+#define IRQ_SPORT2_TX  BFIN_IRQ(34)    /* SPORT2 TX (DMA19) Interrupt */
+#define IRQ_SPORT3_RX  BFIN_IRQ(35)    /* SPORT3 RX (DMA20) Interrupt */
+#define IRQ_SPORT3_TX  BFIN_IRQ(36)    /* SPORT3 TX (DMA21) Interrupt */
+#define IRQ_EPPI1      BFIN_IRQ(37)    /* EPP1 (DMA13) Interrupt */
+#define IRQ_EPPI2      BFIN_IRQ(38)    /* EPP2 (DMA14) Interrupt */
+#define IRQ_SPI1       BFIN_IRQ(39)    /* SPI1 (DMA5) Interrupt */
+#define IRQ_SPI2       BFIN_IRQ(40)    /* SPI2 (DMA23) Interrupt */
+#define IRQ_UART1_RX   BFIN_IRQ(41)    /* UART1 RX (DMA8) Interrupt */
+#define IRQ_UART1_TX   BFIN_IRQ(42)    /* UART1 TX (DMA9) Interrupt */
+#define IRQ_ATAPI_RX   BFIN_IRQ(43)    /* ATAPI RX (DMA10) Interrupt */
+#define IRQ_ATAPI_TX   BFIN_IRQ(44)    /* ATAPI TX (DMA11) Interrupt */
+#define IRQ_TWI0       BFIN_IRQ(45)    /* TWI0 Interrupt */
+#define IRQ_TWI1       BFIN_IRQ(46)    /* TWI1 Interrupt */
+#define IRQ_CAN0_RX    BFIN_IRQ(47)    /* CAN0 Receive Interrupt */
+#define IRQ_CAN0_TX    BFIN_IRQ(48)    /* CAN0 Transmit Interrupt */
+#define IRQ_MDMAS2     BFIN_IRQ(49)    /* MDMA Stream 2 Interrupt */
+#define IRQ_MDMAS3     BFIN_IRQ(50)    /* MDMA Stream 3 Interrupt */
+#define IRQ_MXVR_ERR   BFIN_IRQ(51)    /* MXVR Status (Error) Interrupt */
+#define IRQ_MXVR_MSG   BFIN_IRQ(52)    /* MXVR Message Interrupt */
+#define IRQ_MXVR_PKT   BFIN_IRQ(53)    /* MXVR Packet Interrupt */
+#define IRQ_EPP1_ERR   BFIN_IRQ(54)    /* EPPI1 Error Interrupt */
+#define IRQ_EPP2_ERR   BFIN_IRQ(55)    /* EPPI2 Error Interrupt */
+#define IRQ_UART3_ERR  BFIN_IRQ(56)    /* UART3 Status (Error) Interrupt */
+#define IRQ_HOST_ERR   BFIN_IRQ(57)    /* HOST Status (Error) Interrupt */
+#define IRQ_PIXC_ERR   BFIN_IRQ(59)    /* PIXC Status (Error) Interrupt */
+#define IRQ_NFC_ERR    BFIN_IRQ(60)    /* NFC Error Interrupt */
+#define IRQ_ATAPI_ERR  BFIN_IRQ(61)    /* ATAPI Error Interrupt */
+#define IRQ_CAN1_ERR   BFIN_IRQ(62)    /* CAN1 Status (Error) Interrupt */
+#define IRQ_HS_DMA_ERR BFIN_IRQ(63)    /* Handshake DMA Status Interrupt */
+#define IRQ_PIXC_IN0   BFIN_IRQ(64)    /* PIXC IN0 (DMA15) Interrupt */
+#define IRQ_PIXC_IN1   BFIN_IRQ(65)    /* PIXC IN1 (DMA16) Interrupt */
+#define IRQ_PIXC_OUT   BFIN_IRQ(66)    /* PIXC OUT (DMA17) Interrupt */
+#define IRQ_SDH                BFIN_IRQ(67)    /* SDH/NFC (DMA22) Interrupt */
+#define IRQ_CNT                BFIN_IRQ(68)    /* CNT Interrupt */
+#define IRQ_KEY                BFIN_IRQ(69)    /* KEY Interrupt */
+#define IRQ_CAN1_RX    BFIN_IRQ(70)    /* CAN1 RX Interrupt */
+#define IRQ_CAN1_TX    BFIN_IRQ(71)    /* CAN1 TX Interrupt */
+#define IRQ_SDH_MASK0  BFIN_IRQ(72)    /* SDH Mask 0 Interrupt */
+#define IRQ_SDH_MASK1  BFIN_IRQ(73)    /* SDH Mask 1 Interrupt */
+#define IRQ_USB_INT0   BFIN_IRQ(75)    /* USB INT0 Interrupt */
+#define IRQ_USB_INT1   BFIN_IRQ(76)    /* USB INT1 Interrupt */
+#define IRQ_USB_INT2   BFIN_IRQ(77)    /* USB INT2 Interrupt */
+#define IRQ_USB_DMA    BFIN_IRQ(78)    /* USB DMA Interrupt */
+#define IRQ_OPTSEC     BFIN_IRQ(79)    /* OTPSEC Interrupt */
+#define IRQ_TIMER0     BFIN_IRQ(86)    /* Timer 0 Interrupt */
+#define IRQ_TIMER1     BFIN_IRQ(87)    /* Timer 1 Interrupt */
+#define IRQ_TIMER2     BFIN_IRQ(88)    /* Timer 2 Interrupt */
+#define IRQ_TIMER3     BFIN_IRQ(89)    /* Timer 3 Interrupt */
+#define IRQ_TIMER4     BFIN_IRQ(90)    /* Timer 4 Interrupt */
+#define IRQ_TIMER5     BFIN_IRQ(91)    /* Timer 5 Interrupt */
+#define IRQ_TIMER6     BFIN_IRQ(92)    /* Timer 6 Interrupt */
+#define IRQ_TIMER7     BFIN_IRQ(93)    /* Timer 7 Interrupt */
+#define IRQ_PINT2      BFIN_IRQ(94)    /* PINT2 Interrupt */
+#define IRQ_PINT3      BFIN_IRQ(95)    /* PINT3 Interrupt */
+
+#define SYS_IRQS        IRQ_PINT3
+
+#define BFIN_PA_IRQ(x) ((x) + SYS_IRQS + 1)
+#define IRQ_PA0                BFIN_PA_IRQ(0)
+#define IRQ_PA1                BFIN_PA_IRQ(1)
+#define IRQ_PA2                BFIN_PA_IRQ(2)
+#define IRQ_PA3                BFIN_PA_IRQ(3)
+#define IRQ_PA4                BFIN_PA_IRQ(4)
+#define IRQ_PA5                BFIN_PA_IRQ(5)
+#define IRQ_PA6                BFIN_PA_IRQ(6)
+#define IRQ_PA7                BFIN_PA_IRQ(7)
+#define IRQ_PA8                BFIN_PA_IRQ(8)
+#define IRQ_PA9                BFIN_PA_IRQ(9)
+#define IRQ_PA10       BFIN_PA_IRQ(10)
+#define IRQ_PA11       BFIN_PA_IRQ(11)
+#define IRQ_PA12       BFIN_PA_IRQ(12)
+#define IRQ_PA13       BFIN_PA_IRQ(13)
+#define IRQ_PA14       BFIN_PA_IRQ(14)
+#define IRQ_PA15       BFIN_PA_IRQ(15)
+
+#define BFIN_PB_IRQ(x) ((x) + IRQ_PA15 + 1)
+#define IRQ_PB0                BFIN_PB_IRQ(0)
+#define IRQ_PB1                BFIN_PB_IRQ(1)
+#define IRQ_PB2                BFIN_PB_IRQ(2)
+#define IRQ_PB3                BFIN_PB_IRQ(3)
+#define IRQ_PB4                BFIN_PB_IRQ(4)
+#define IRQ_PB5                BFIN_PB_IRQ(5)
+#define IRQ_PB6                BFIN_PB_IRQ(6)
+#define IRQ_PB7                BFIN_PB_IRQ(7)
+#define IRQ_PB8                BFIN_PB_IRQ(8)
+#define IRQ_PB9                BFIN_PB_IRQ(9)
+#define IRQ_PB10       BFIN_PB_IRQ(10)
+#define IRQ_PB11       BFIN_PB_IRQ(11)
+#define IRQ_PB12       BFIN_PB_IRQ(12)
+#define IRQ_PB13       BFIN_PB_IRQ(13)
+#define IRQ_PB14       BFIN_PB_IRQ(14)
+#define IRQ_PB15       BFIN_PB_IRQ(15)         /* N/A */
+
+#define BFIN_PC_IRQ(x) ((x) + IRQ_PB15 + 1)
+#define IRQ_PC0                BFIN_PC_IRQ(0)
+#define IRQ_PC1                BFIN_PC_IRQ(1)
+#define IRQ_PC2                BFIN_PC_IRQ(2)
+#define IRQ_PC3                BFIN_PC_IRQ(3)
+#define IRQ_PC4                BFIN_PC_IRQ(4)
+#define IRQ_PC5                BFIN_PC_IRQ(5)
+#define IRQ_PC6                BFIN_PC_IRQ(6)
+#define IRQ_PC7                BFIN_PC_IRQ(7)
+#define IRQ_PC8                BFIN_PC_IRQ(8)
+#define IRQ_PC9                BFIN_PC_IRQ(9)
+#define IRQ_PC10       BFIN_PC_IRQ(10)
+#define IRQ_PC11       BFIN_PC_IRQ(11)
+#define IRQ_PC12       BFIN_PC_IRQ(12)
+#define IRQ_PC13       BFIN_PC_IRQ(13)
+#define IRQ_PC14       BFIN_PC_IRQ(14)         /* N/A */
+#define IRQ_PC15       BFIN_PC_IRQ(15)         /* N/A */
+
+#define BFIN_PD_IRQ(x) ((x) + IRQ_PC15 + 1)
+#define IRQ_PD0                BFIN_PD_IRQ(0)
+#define IRQ_PD1                BFIN_PD_IRQ(1)
+#define IRQ_PD2                BFIN_PD_IRQ(2)
+#define IRQ_PD3                BFIN_PD_IRQ(3)
+#define IRQ_PD4                BFIN_PD_IRQ(4)
+#define IRQ_PD5                BFIN_PD_IRQ(5)
+#define IRQ_PD6                BFIN_PD_IRQ(6)
+#define IRQ_PD7                BFIN_PD_IRQ(7)
+#define IRQ_PD8                BFIN_PD_IRQ(8)
+#define IRQ_PD9                BFIN_PD_IRQ(9)
+#define IRQ_PD10       BFIN_PD_IRQ(10)
+#define IRQ_PD11       BFIN_PD_IRQ(11)
+#define IRQ_PD12       BFIN_PD_IRQ(12)
+#define IRQ_PD13       BFIN_PD_IRQ(13)
+#define IRQ_PD14       BFIN_PD_IRQ(14)
+#define IRQ_PD15       BFIN_PD_IRQ(15)
+
+#define BFIN_PE_IRQ(x) ((x) + IRQ_PD15 + 1)
+#define IRQ_PE0                BFIN_PE_IRQ(0)
+#define IRQ_PE1                BFIN_PE_IRQ(1)
+#define IRQ_PE2                BFIN_PE_IRQ(2)
+#define IRQ_PE3                BFIN_PE_IRQ(3)
+#define IRQ_PE4                BFIN_PE_IRQ(4)
+#define IRQ_PE5                BFIN_PE_IRQ(5)
+#define IRQ_PE6                BFIN_PE_IRQ(6)
+#define IRQ_PE7                BFIN_PE_IRQ(7)
+#define IRQ_PE8                BFIN_PE_IRQ(8)
+#define IRQ_PE9                BFIN_PE_IRQ(9)
+#define IRQ_PE10       BFIN_PE_IRQ(10)
+#define IRQ_PE11       BFIN_PE_IRQ(11)
+#define IRQ_PE12       BFIN_PE_IRQ(12)
+#define IRQ_PE13       BFIN_PE_IRQ(13)
+#define IRQ_PE14       BFIN_PE_IRQ(14)
+#define IRQ_PE15       BFIN_PE_IRQ(15)
+
+#define BFIN_PF_IRQ(x) ((x) + IRQ_PE15 + 1)
+#define IRQ_PF0                BFIN_PF_IRQ(0)
+#define IRQ_PF1                BFIN_PF_IRQ(1)
+#define IRQ_PF2                BFIN_PF_IRQ(2)
+#define IRQ_PF3                BFIN_PF_IRQ(3)
+#define IRQ_PF4                BFIN_PF_IRQ(4)
+#define IRQ_PF5                BFIN_PF_IRQ(5)
+#define IRQ_PF6                BFIN_PF_IRQ(6)
+#define IRQ_PF7                BFIN_PF_IRQ(7)
+#define IRQ_PF8                BFIN_PF_IRQ(8)
+#define IRQ_PF9                BFIN_PF_IRQ(9)
+#define IRQ_PF10       BFIN_PF_IRQ(10)
+#define IRQ_PF11       BFIN_PF_IRQ(11)
+#define IRQ_PF12       BFIN_PF_IRQ(12)
+#define IRQ_PF13       BFIN_PF_IRQ(13)
+#define IRQ_PF14       BFIN_PF_IRQ(14)
+#define IRQ_PF15       BFIN_PF_IRQ(15)
+
+#define BFIN_PG_IRQ(x) ((x) + IRQ_PF15 + 1)
+#define IRQ_PG0                BFIN_PG_IRQ(0)
+#define IRQ_PG1                BFIN_PG_IRQ(1)
+#define IRQ_PG2                BFIN_PG_IRQ(2)
+#define IRQ_PG3                BFIN_PG_IRQ(3)
+#define IRQ_PG4                BFIN_PG_IRQ(4)
+#define IRQ_PG5                BFIN_PG_IRQ(5)
+#define IRQ_PG6                BFIN_PG_IRQ(6)
+#define IRQ_PG7                BFIN_PG_IRQ(7)
+#define IRQ_PG8                BFIN_PG_IRQ(8)
+#define IRQ_PG9                BFIN_PG_IRQ(9)
+#define IRQ_PG10       BFIN_PG_IRQ(10)
+#define IRQ_PG11       BFIN_PG_IRQ(11)
+#define IRQ_PG12       BFIN_PG_IRQ(12)
+#define IRQ_PG13       BFIN_PG_IRQ(13)
+#define IRQ_PG14       BFIN_PG_IRQ(14)
+#define IRQ_PG15       BFIN_PG_IRQ(15)
+
+#define BFIN_PH_IRQ(x) ((x) + IRQ_PG15 + 1)
+#define IRQ_PH0                BFIN_PH_IRQ(0)
+#define IRQ_PH1                BFIN_PH_IRQ(1)
+#define IRQ_PH2                BFIN_PH_IRQ(2)
+#define IRQ_PH3                BFIN_PH_IRQ(3)
+#define IRQ_PH4                BFIN_PH_IRQ(4)
+#define IRQ_PH5                BFIN_PH_IRQ(5)
+#define IRQ_PH6                BFIN_PH_IRQ(6)
+#define IRQ_PH7                BFIN_PH_IRQ(7)
+#define IRQ_PH8                BFIN_PH_IRQ(8)
+#define IRQ_PH9                BFIN_PH_IRQ(9)
+#define IRQ_PH10       BFIN_PH_IRQ(10)
+#define IRQ_PH11       BFIN_PH_IRQ(11)
+#define IRQ_PH12       BFIN_PH_IRQ(12)
+#define IRQ_PH13       BFIN_PH_IRQ(13)
+#define IRQ_PH14       BFIN_PH_IRQ(14)         /* N/A */
+#define IRQ_PH15       BFIN_PH_IRQ(15)         /* N/A */
+
+#define BFIN_PI_IRQ(x) ((x) + IRQ_PH15 + 1)
+#define IRQ_PI0                BFIN_PI_IRQ(0)
+#define IRQ_PI1                BFIN_PI_IRQ(1)
+#define IRQ_PI2                BFIN_PI_IRQ(2)
+#define IRQ_PI3                BFIN_PI_IRQ(3)
+#define IRQ_PI4                BFIN_PI_IRQ(4)
+#define IRQ_PI5                BFIN_PI_IRQ(5)
+#define IRQ_PI6                BFIN_PI_IRQ(6)
+#define IRQ_PI7                BFIN_PI_IRQ(7)
+#define IRQ_PI8                BFIN_PI_IRQ(8)
+#define IRQ_PI9                BFIN_PI_IRQ(9)
+#define IRQ_PI10       BFIN_PI_IRQ(10)
+#define IRQ_PI11       BFIN_PI_IRQ(11)
+#define IRQ_PI12       BFIN_PI_IRQ(12)
+#define IRQ_PI13       BFIN_PI_IRQ(13)
+#define IRQ_PI14       BFIN_PI_IRQ(14)
+#define IRQ_PI15       BFIN_PI_IRQ(15)
+
+#define BFIN_PJ_IRQ(x) ((x) + IRQ_PI15 + 1)
+#define IRQ_PJ0                BFIN_PJ_IRQ(0)
+#define IRQ_PJ1                BFIN_PJ_IRQ(1)
+#define IRQ_PJ2                BFIN_PJ_IRQ(2)
+#define IRQ_PJ3                BFIN_PJ_IRQ(3)
+#define IRQ_PJ4                BFIN_PJ_IRQ(4)
+#define IRQ_PJ5                BFIN_PJ_IRQ(5)
+#define IRQ_PJ6                BFIN_PJ_IRQ(6)
+#define IRQ_PJ7                BFIN_PJ_IRQ(7)
+#define IRQ_PJ8                BFIN_PJ_IRQ(8)
+#define IRQ_PJ9                BFIN_PJ_IRQ(9)
+#define IRQ_PJ10       BFIN_PJ_IRQ(10)
+#define IRQ_PJ11       BFIN_PJ_IRQ(11)
+#define IRQ_PJ12       BFIN_PJ_IRQ(12)
+#define IRQ_PJ13       BFIN_PJ_IRQ(13)
+#define IRQ_PJ14       BFIN_PJ_IRQ(14)         /* N/A */
+#define IRQ_PJ15       BFIN_PJ_IRQ(15)         /* N/A */
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#define NR_IRQS     (IRQ_PJ15+1)
+#else
+#define NR_IRQS     (SYS_IRQS+1)
+#endif
+
+#define IVG7            7
+#define IVG8            8
+#define IVG9            9
+#define IVG10           10
+#define IVG11           11
+#define IVG12           12
+#define IVG13           13
+#define IVG14           14
+#define IVG15           15
+
+/* IAR0 BIT FIELDS */
+#define IRQ_PLL_WAKEUP_POS     0
+#define IRQ_DMAC0_ERR_POS      4
+#define IRQ_EPPI0_ERR_POS      8
+#define IRQ_SPORT0_ERR_POS     12
+#define IRQ_SPORT1_ERR_POS     16
+#define IRQ_SPI0_ERR_POS       20
+#define IRQ_UART0_ERR_POS      24
+#define IRQ_RTC_POS            28
+
+/* IAR1 BIT FIELDS */
+#define IRQ_EPPI0_POS          0
+#define IRQ_SPORT0_RX_POS      4
+#define IRQ_SPORT0_TX_POS      8
+#define IRQ_SPORT1_RX_POS      12
+#define IRQ_SPORT1_TX_POS      16
+#define IRQ_SPI0_POS           20
+#define IRQ_UART0_RX_POS       24
+#define IRQ_UART0_TX_POS       28
+
+/* IAR2 BIT FIELDS */
+#define IRQ_TIMER8_POS         0
+#define IRQ_TIMER9_POS         4
+#define IRQ_TIMER10_POS                8
+#define IRQ_PINT0_POS          12
+#define IRQ_PINT1_POS          16
+#define IRQ_MDMAS0_POS         20
+#define IRQ_MDMAS1_POS         24
+#define IRQ_WATCHDOG_POS       28
+
+/* IAR3 BIT FIELDS */
+#define IRQ_DMAC1_ERR_POS      0
+#define IRQ_SPORT2_ERR_POS     4
+#define IRQ_SPORT3_ERR_POS     8
+#define IRQ_MXVR_DATA_POS      12
+#define IRQ_SPI1_ERR_POS       16
+#define IRQ_SPI2_ERR_POS       20
+#define IRQ_UART1_ERR_POS      24
+#define IRQ_UART2_ERR_POS      28
+
+/* IAR4 BIT FILEDS */
+#define IRQ_CAN0_ERR_POS       0
+#define IRQ_SPORT2_RX_POS      4
+#define IRQ_SPORT2_TX_POS      8
+#define IRQ_SPORT3_RX_POS      12
+#define IRQ_SPORT3_TX_POS      16
+#define IRQ_EPPI1_POS          20
+#define IRQ_EPPI2_POS          24
+#define IRQ_SPI1_POS           28
+
+/* IAR5 BIT FIELDS */
+#define IRQ_SPI2_POS           0
+#define IRQ_UART1_RX_POS       4
+#define IRQ_UART1_TX_POS       8
+#define IRQ_ATAPI_RX_POS       12
+#define IRQ_ATAPI_TX_POS       16
+#define IRQ_TWI0_POS           20
+#define IRQ_TWI1_POS           24
+#define IRQ_CAN0_RX_POS                28
+
+/* IAR6 BIT FIELDS */
+#define IRQ_CAN0_TX_POS                0
+#define IRQ_MDMAS2_POS         4
+#define IRQ_MDMAS3_POS         8
+#define IRQ_MXVR_ERR_POS       12
+#define IRQ_MXVR_MSG_POS       16
+#define IRQ_MXVR_PKT_POS       20
+#define IRQ_EPPI1_ERR_POS      24
+#define IRQ_EPPI2_ERR_POS      28
+
+/* IAR7 BIT FIELDS */
+#define IRQ_UART3_ERR_POS      0
+#define IRQ_HOST_ERR_POS       4
+#define IRQ_PIXC_ERR_POS       12
+#define IRQ_NFC_ERR_POS                16
+#define IRQ_ATAPI_ERR_POS      20
+#define IRQ_CAN1_ERR_POS       24
+#define IRQ_HS_DMA_ERR_POS     28
+
+/* IAR8 BIT FIELDS */
+#define IRQ_PIXC_IN0_POS       0
+#define IRQ_PIXC_IN1_POS       4
+#define IRQ_PIXC_OUT_POS       8
+#define IRQ_SDH_POS            12
+#define IRQ_CNT_POS            16
+#define IRQ_KEY_POS            20
+#define IRQ_CAN1_RX_POS                24
+#define IRQ_CAN1_TX_POS                28
+
+/* IAR9 BIT FIELDS */
+#define IRQ_SDH_MASK0_POS      0
+#define IRQ_SDH_MASK1_POS      4
+#define IRQ_USB_INT0_POS       12
+#define IRQ_USB_INT1_POS       16
+#define IRQ_USB_INT2_POS       20
+#define IRQ_USB_DMA_POS                24
+#define IRQ_OTPSEC_POS         28
+
+/* IAR10 BIT FIELDS */
+#define IRQ_TIMER0_POS         24
+#define IRQ_TIMER1_POS         28
+
+/* IAR11 BIT FIELDS */
+#define IRQ_TIMER2_POS         0
+#define IRQ_TIMER3_POS         4
+#define IRQ_TIMER4_POS         8
+#define IRQ_TIMER5_POS         12
+#define IRQ_TIMER6_POS         16
+#define IRQ_TIMER7_POS         20
+#define IRQ_PINT2_POS          24
+#define IRQ_PINT3_POS          28
+
+#endif /* _BF548_IRQ_H_ */
diff --git a/include/asm-blackfin/mach-bf548/mem_init.h b/include/asm-blackfin/mach-bf548/mem_init.h
new file mode 100644 (file)
index 0000000..0cb279e
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/mem_init.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * 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, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#if (CONFIG_MEM_MT46V32M16)
+
+#if defined CONFIG_CLKIN_HALF
+#define CLKIN_HALF       1
+#else
+#define CLKIN_HALF       0
+#endif
+
+#if defined CONFIG_PLL_BYPASS
+#define PLL_BYPASS      1
+#else
+#define PLL_BYPASS       0
+#endif
+
+/***************************************Currently Not Being Used *********************************/
+#define flash_EBIU_AMBCTL_WAT  ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_RAT  ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_HT   ((CONFIG_FLASH_SPEED_BHT  * 4) / (4000000000 / CONFIG_SCLK_HZ))
+#define flash_EBIU_AMBCTL_ST   ((CONFIG_FLASH_SPEED_BST  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_TT   ((CONFIG_FLASH_SPEED_BTT  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+
+#if (flash_EBIU_AMBCTL_TT > 3)
+#define flash_EBIU_AMBCTL0_TT   B0TT_4
+#endif
+#if (flash_EBIU_AMBCTL_TT == 3)
+#define flash_EBIU_AMBCTL0_TT   B0TT_3
+#endif
+#if (flash_EBIU_AMBCTL_TT == 2)
+#define flash_EBIU_AMBCTL0_TT   B0TT_2
+#endif
+#if (flash_EBIU_AMBCTL_TT < 2)
+#define flash_EBIU_AMBCTL0_TT   B0TT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_ST > 3)
+#define flash_EBIU_AMBCTL0_ST   B0ST_4
+#endif
+#if (flash_EBIU_AMBCTL_ST == 3)
+#define flash_EBIU_AMBCTL0_ST   B0ST_3
+#endif
+#if (flash_EBIU_AMBCTL_ST == 2)
+#define flash_EBIU_AMBCTL0_ST   B0ST_2
+#endif
+#if (flash_EBIU_AMBCTL_ST < 2)
+#define flash_EBIU_AMBCTL0_ST   B0ST_1
+#endif
+
+#if (flash_EBIU_AMBCTL_HT > 2)
+#define flash_EBIU_AMBCTL0_HT   B0HT_3
+#endif
+#if (flash_EBIU_AMBCTL_HT == 2)
+#define flash_EBIU_AMBCTL0_HT   B0HT_2
+#endif
+#if (flash_EBIU_AMBCTL_HT == 1)
+#define flash_EBIU_AMBCTL0_HT   B0HT_1
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
+#define flash_EBIU_AMBCTL0_HT   B0HT_0
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
+#define flash_EBIU_AMBCTL0_HT   B0HT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_WAT > 14)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_15
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 14)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_14
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 13)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_13
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 12)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_12
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 11)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_11
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 10)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_10
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 9)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_9
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 8)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_8
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 7)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_7
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 6)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_6
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 5)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_5
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 4)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_4
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 3)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_3
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 2)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_2
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 1)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_RAT > 14)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_15
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 14)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_14
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 13)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_13
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 12)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_12
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 11)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_11
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 10)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_10
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 9)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_9
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 8)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_8
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 7)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_7
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 6)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_6
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 5)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_5
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 4)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_4
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 3)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_3
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 2)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_2
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 1)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_1
+#endif
+
+#define flash_EBIU_AMBCTL0  \
+       (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
+        flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
diff --git a/include/asm-blackfin/mach-bf548/mem_map.h b/include/asm-blackfin/mach-bf548/mem_map.h
new file mode 100644 (file)
index 0000000..72d80e8
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * file:         include/asm-blackfin/mach-bf548/mem_map.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *     Memory MAP Common header file for blackfin BF537/6/4 of processors.
+ * rev:
+ *
+ * modified:
+ *
+ * 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, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _MEM_MAP_548_H_
+#define _MEM_MAP_548_H_
+
+#define COREMMR_BASE           0xFFE00000       /* Core MMRs */
+#define SYSMMR_BASE            0xFFC00000       /* System MMRs */
+
+/* Async Memory Banks */
+#define ASYNC_BANK3_BASE       0x2C000000       /* Async Bank 3 */
+#define ASYNC_BANK3_SIZE       0x04000000      /* 64M */
+#define ASYNC_BANK2_BASE       0x28000000       /* Async Bank 2 */
+#define ASYNC_BANK2_SIZE       0x04000000      /* 64M */
+#define ASYNC_BANK1_BASE       0x24000000       /* Async Bank 1 */
+#define ASYNC_BANK1_SIZE       0x04000000      /* 64M */
+#define ASYNC_BANK0_BASE       0x20000000       /* Async Bank 0 */
+#define ASYNC_BANK0_SIZE       0x04000000      /* 64M */
+
+/* Boot ROM Memory */
+
+#define BOOT_ROM_START         0xEF000000
+
+/* Level 1 Memory */
+
+/* Memory Map for ADSP-BF548 processors */
+#ifdef CONFIG_BLKFIN_ICACHE
+#define BLKFIN_ICACHESIZE      (16*1024)
+#else
+#define BLKFIN_ICACHESIZE      (0*1024)
+#endif
+
+#define L1_CODE_START       0xFFA00000
+#define L1_DATA_A_START     0xFF800000
+#define L1_DATA_B_START     0xFF900000
+
+#define L1_CODE_LENGTH      0xC000
+
+#ifdef CONFIG_BLKFIN_DCACHE
+
+#ifdef CONFIG_BLKFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE      (16*1024)
+#define BLKFIN_DSUPBANKS       1
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      (0x8000 - 0x4000)
+#define BLKFIN_DCACHESIZE      (32*1024)
+#define BLKFIN_DSUPBANKS       2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      0x8000
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE      (0*1024)
+#define BLKFIN_DSUPBANKS       0
+#endif /*CONFIG_BLKFIN_DCACHE*/
+
+/* Scratch Pad Memory */
+
+#if defined(CONFIG_BF54x)
+#define L1_SCRATCH_START       0xFFB00000
+#define L1_SCRATCH_LENGTH      0x1000
+#endif
+
+#endif/* _MEM_MAP_548_H_ */
diff --git a/include/asm-blackfin/mach-bf548/portmux.h b/include/asm-blackfin/mach-bf548/portmux.h
new file mode 100644 (file)
index 0000000..b382deb
--- /dev/null
@@ -0,0 +1,270 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_SPORT2_TFS   (P_DEFINED | P_IDENT(GPIO_PA0) | P_FUNCT(0))
+#define P_SPORT2_DTSEC (P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(0))
+#define P_SPORT2_DTPRI (P_DEFINED | P_IDENT(GPIO_PA2) | P_FUNCT(0))
+#define P_SPORT2_TSCLK (P_DEFINED | P_IDENT(GPIO_PA3) | P_FUNCT(0))
+#define P_SPORT2_RFS   (P_DEFINED | P_IDENT(GPIO_PA4) | P_FUNCT(0))
+#define P_SPORT2_DRSEC (P_DEFINED | P_IDENT(GPIO_PA5) | P_FUNCT(0))
+#define P_SPORT2_DRPRI (P_DEFINED | P_IDENT(GPIO_PA6) | P_FUNCT(0))
+#define P_SPORT2_RSCLK (P_DEFINED | P_IDENT(GPIO_PA7) | P_FUNCT(0))
+#define P_SPORT3_TFS   (P_DEFINED | P_IDENT(GPIO_PA8) | P_FUNCT(0))
+#define P_SPORT3_DTSEC (P_DEFINED | P_IDENT(GPIO_PA9) | P_FUNCT(0))
+#define P_SPORT3_DTPRI (P_DEFINED | P_IDENT(GPIO_PA10) | P_FUNCT(0))
+#define P_SPORT3_TSCLK (P_DEFINED | P_IDENT(GPIO_PA11) | P_FUNCT(0))
+#define P_SPORT3_RFS   (P_DEFINED | P_IDENT(GPIO_PA12) | P_FUNCT(0))
+#define P_SPORT3_DRSEC (P_DEFINED | P_IDENT(GPIO_PA13) | P_FUNCT(0))
+#define P_SPORT3_DRPRI (P_DEFINED | P_IDENT(GPIO_PA14) | P_FUNCT(0))
+#define P_SPORT3_RSCLK (P_DEFINED | P_IDENT(GPIO_PA15) | P_FUNCT(0))
+#define P_TMR4 (P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(1))
+#define P_TMR5 (P_DEFINED | P_IDENT(GPIO_PA5) | P_FUNCT(1))
+#define P_TMR6 (P_DEFINED | P_IDENT(GPIO_PA9) | P_FUNCT(1))
+#define P_TMR7 (P_DEFINED | P_IDENT(GPIO_PA13) | P_FUNCT(1))
+
+#define P_TWI1_SCL     (P_DEFINED | P_IDENT(GPIO_PB0) | P_FUNCT(0))
+#define P_TWI1_SDA     (P_DEFINED | P_IDENT(GPIO_PB1) | P_FUNCT(0))
+#define P_UART3_RTS    (P_DEFINED | P_IDENT(GPIO_PB2) | P_FUNCT(0))
+#define P_UART3_CTS    (P_DEFINED | P_IDENT(GPIO_PB3) | P_FUNCT(0))
+#define P_UART2_TX     (P_DEFINED | P_IDENT(GPIO_PB4) | P_FUNCT(0))
+#define P_UART2_RX     (P_DEFINED | P_IDENT(GPIO_PB5) | P_FUNCT(0))
+#define P_UART3_TX     (P_DEFINED | P_IDENT(GPIO_PB6) | P_FUNCT(0))
+#define P_UART3_RX     (P_DEFINED | P_IDENT(GPIO_PB7) | P_FUNCT(0))
+#define P_SPI2_SS      (P_DEFINED | P_IDENT(GPIO_PB8) | P_FUNCT(0))
+#define P_SPI2_SSEL1   (P_DEFINED | P_IDENT(GPIO_PB9) | P_FUNCT(0))
+#define P_SPI2_SSEL2   (P_DEFINED | P_IDENT(GPIO_PB10) | P_FUNCT(0))
+#define P_SPI2_SSEL3   (P_DEFINED | P_IDENT(GPIO_PB11) | P_FUNCT(0))
+#define P_SPI2_SCK     (P_DEFINED | P_IDENT(GPIO_PB12) | P_FUNCT(0))
+#define P_SPI2_MOSI    (P_DEFINED | P_IDENT(GPIO_PB13) | P_FUNCT(0))
+#define P_SPI2_MISO    (P_DEFINED | P_IDENT(GPIO_PB14) | P_FUNCT(0))
+#define P_TMR0 (P_DEFINED | P_IDENT(GPIO_PB8) | P_FUNCT(1))
+#define P_TMR1 (P_DEFINED | P_IDENT(GPIO_PB9) | P_FUNCT(1))
+#define P_TMR2 (P_DEFINED | P_IDENT(GPIO_PB10) | P_FUNCT(1))
+#define P_TMR3 (P_DEFINED | P_IDENT(GPIO_PB11) | P_FUNCT(1))
+
+#define P_SPORT0_TFS   (P_DEFINED | P_IDENT(GPIO_PC0) | P_FUNCT(0))
+#define P_SPORT0_DTSEC (P_DEFINED | P_IDENT(GPIO_PC1) | P_FUNCT(0))
+#define P_SPORT0_DTPRI (P_DEFINED | P_IDENT(GPIO_PC2) | P_FUNCT(0))
+#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(GPIO_PC3) | P_FUNCT(0))
+#define P_SPORT0_RFS   (P_DEFINED | P_IDENT(GPIO_PC4) | P_FUNCT(0))
+#define P_SPORT0_DRSEC (P_DEFINED | P_IDENT(GPIO_PC5) | P_FUNCT(0))
+#define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(GPIO_PC6) | P_FUNCT(0))
+#define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PC7) | P_FUNCT(0))
+#define P_SD_D0        (P_DEFINED | P_IDENT(GPIO_PC8) | P_FUNCT(0))
+#define P_SD_D1        (P_DEFINED | P_IDENT(GPIO_PC9) | P_FUNCT(0))
+#define P_SD_D2        (P_DEFINED | P_IDENT(GPIO_PC10) | P_FUNCT(0))
+#define P_SD_D3        (P_DEFINED | P_IDENT(GPIO_PC11) | P_FUNCT(0))
+#define P_SD_CLK       (P_DEFINED | P_IDENT(GPIO_PC12) | P_FUNCT(0))
+#define P_SD_CMD       (P_DEFINED | P_IDENT(GPIO_PC13) | P_FUNCT(0))
+#define P_MMCLK        (P_DEFINED | P_IDENT(GPIO_PC1) | P_FUNCT(1))
+#define P_MBCLK        (P_DEFINED | P_IDENT(GPIO_PC5) | P_FUNCT(1))
+
+#define P_PPI1_D0      (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(0))
+#define P_PPI1_D1      (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(0))
+#define P_PPI1_D2      (P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(0))
+#define P_PPI1_D3      (P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(0))
+#define P_PPI1_D4      (P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(0))
+#define P_PPI1_D5      (P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(0))
+#define P_PPI1_D6      (P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(0))
+#define P_PPI1_D7      (P_DEFINED | P_IDENT(GPIO_PD7) | P_FUNCT(0))
+#define P_PPI1_D8      (P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(0))
+#define P_PPI1_D9      (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(0))
+#define P_PPI1_D10     (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(0))
+#define P_PPI1_D11     (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(0))
+#define P_PPI1_D12     (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(0))
+#define P_PPI1_D13     (P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(0))
+#define P_PPI1_D14     (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(0))
+#define P_PPI1_D15     (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(0))
+
+#define P_HOST_D8      (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(1))
+#define P_HOST_D9      (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(1))
+#define P_HOST_D10     (P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(1))
+#define P_HOST_D11     (P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(1))
+#define P_HOST_D12     (P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(1))
+#define P_HOST_D13     (P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(1))
+#define P_HOST_D14     (P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(1))
+#define P_HOST_D15     (P_DEFINED | P_IDENT(GPIO_PD7) | P_FUNCT(1))
+#define P_HOST_D0      (P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(1))
+#define P_HOST_D1      (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(1))
+#define P_HOST_D2      (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(1))
+#define P_HOST_D3      (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(1))
+#define P_HOST_D4      (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(1))
+#define P_HOST_D5      (P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(1))
+#define P_HOST_D6      (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(1))
+#define P_HOST_D7      (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(1))
+#define P_SPORT1_TFS   (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(2))
+#define P_SPORT1_DTSEC (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(2))
+#define P_SPORT1_DTPRI (P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(2))
+#define P_SPORT1_TSCLK (P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(2))
+#define P_SPORT1_RFS   (P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(2))
+#define P_SPORT1_DRSEC (P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(2))
+#define P_SPORT1_DRPRI (P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(2))
+#define P_SPORT1_RSCLK (P_DEFINED | P_IDENT(GPIO_PD7) | P_FUNCT(2))
+#define P_PPI2_D0      (P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(2))
+#define P_PPI2_D1      (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(2))
+#define P_PPI2_D2      (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(2))
+#define P_PPI2_D3      (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(2))
+#define P_PPI2_D4      (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(2))
+#define P_PPI2_D5      (P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(2))
+#define P_PPI2_D6      (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(2))
+#define P_PPI2_D7      (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(2))
+#define P_PPI0_D18     (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(3))
+#define P_PPI0_D19     (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(3))
+#define P_PPI0_D20     (P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(3))
+#define P_PPI0_D21     (P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(3))
+#define P_PPI0_D22     (P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(3))
+#define P_PPI0_D23     (P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(3))
+#define P_KEY_ROW0     (P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(3))
+#define P_KEY_ROW1     (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(3))
+#define P_KEY_ROW2     (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(3))
+#define P_KEY_ROW3     (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(3))
+#define P_KEY_COL0     (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(3))
+#define P_KEY_COL1     (P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(3))
+#define P_KEY_COL2     (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(3))
+#define P_KEY_COL3     (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(3))
+
+#define P_SPI0_SCK     (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(0))
+#define P_SPI0_MISO    (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(0))
+#define P_SPI0_MOSI    (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(0))
+#define P_SPI0_SS      (P_DEFINED | P_IDENT(GPIO_PE3) | P_FUNCT(0))
+#define P_SPI0_SSEL1   (P_DEFINED | P_IDENT(GPIO_PE4) | P_FUNCT(0))
+#define P_SPI0_SSEL2   (P_DEFINED | P_IDENT(GPIO_PE5) | P_FUNCT(0))
+#define P_SPI0_SSEL3   (P_DEFINED | P_IDENT(GPIO_PE6) | P_FUNCT(0))
+#define P_UART0_TX     (P_DEFINED | P_IDENT(GPIO_PE7) | P_FUNCT(0))
+#define P_UART0_RX     (P_DEFINED | P_IDENT(GPIO_PE8) | P_FUNCT(0))
+#define P_UART1_RTS    (P_DEFINED | P_IDENT(GPIO_PE9) | P_FUNCT(0))
+#define P_UART1_CTS    (P_DEFINED | P_IDENT(GPIO_PE10) | P_FUNCT(0))
+#define P_PPI1_CLK     (P_DEFINED | P_IDENT(GPIO_PE11) | P_FUNCT(0))
+#define P_PPI1_FS1     (P_DEFINED | P_IDENT(GPIO_PE12) | P_FUNCT(0))
+#define P_PPI1_FS2     (P_DEFINED | P_IDENT(GPIO_PE13) | P_FUNCT(0))
+#define P_TWI0_SCL     (P_DEFINED | P_IDENT(GPIO_PE14) | P_FUNCT(0))
+#define P_TWI0_SDA     (P_DEFINED | P_IDENT(GPIO_PE15) | P_FUNCT(0))
+#define P_KEY_COL7     (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(1))
+#define P_KEY_ROW6     (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(1))
+#define P_KEY_COL6     (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(1))
+#define P_KEY_ROW5     (P_DEFINED | P_IDENT(GPIO_PE3) | P_FUNCT(1))
+#define P_KEY_COL5     (P_DEFINED | P_IDENT(GPIO_PE4) | P_FUNCT(1))
+#define P_KEY_ROW4     (P_DEFINED | P_IDENT(GPIO_PE5) | P_FUNCT(1))
+#define P_KEY_COL4     (P_DEFINED | P_IDENT(GPIO_PE6) | P_FUNCT(1))
+#define P_KEY_ROW7     (P_DEFINED | P_IDENT(GPIO_PE7) | P_FUNCT(1))
+
+#define P_PPI0_D0      (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(0))
+#define P_PPI0_D1      (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(0))
+#define P_PPI0_D2      (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(0))
+#define P_PPI0_D3      (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(0))
+#define P_PPI0_D4      (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(0))
+#define P_PPI0_D5      (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(0))
+#define P_PPI0_D6      (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(0))
+#define P_PPI0_D7      (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(0))
+#define P_PPI0_D8      (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(0))
+#define P_PPI0_D9      (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(0))
+#define P_PPI0_D10     (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(0))
+#define P_PPI0_D11     (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(0))
+#define P_PPI0_D12     (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(0))
+#define P_PPI0_D13     (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(0))
+#define P_PPI0_D14     (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(0))
+#define P_PPI0_D15     (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(0))
+#define P_ATAPI_D0A    (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1))
+#define P_ATAPI_D1A    (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1))
+#define P_ATAPI_D2A    (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1))
+#define P_ATAPI_D3A    (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1))
+#define P_ATAPI_D4A    (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1))
+#define P_ATAPI_D5A    (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1))
+#define P_ATAPI_D6A    (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1))
+#define P_ATAPI_D7A    (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1))
+#define P_ATAPI_D8A    (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1))
+#define P_ATAPI_D9A    (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
+#define P_ATAPI_D10A   (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(1))
+#define P_ATAPI_D11A   (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(1))
+#define P_ATAPI_D12A   (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(1))
+#define P_ATAPI_D13A   (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(1))
+#define P_ATAPI_D14A   (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
+#define P_ATAPI_D15A   (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+
+#define P_PPI0_CLK     (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0))
+#define P_PPI0_FS1     (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
+#define P_PPI0_FS2     (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(0))
+#define P_PPI0_D16     (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0))
+#define P_PPI0_D17     (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(0))
+#define P_SPI1_SSEL1   (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0))
+#define P_SPI1_SSEL2   (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(0))
+#define P_SPI1_SSEL3   (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(0))
+#define P_SPI1_SCK     (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(0))
+#define P_SPI1_MISO    (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(0))
+#define P_SPI1_MOSI    (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(0))
+#define P_SPI1_SS      (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(0))
+#define P_CAN0_TX      (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(0))
+#define P_CAN0_RX      (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0))
+#define P_CAN1_TX      (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0))
+#define P_CAN1_RX      (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0))
+#define P_ATAPI_A0A    (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(1))
+#define P_ATAPI_A1A    (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(1))
+#define P_ATAPI_A2A    (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(1))
+#define P_HOST_CE      (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(1))
+#define P_HOST_RD      (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(1))
+#define P_HOST_WR      (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(1))
+#define P_MTXONB       (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(1))
+#define P_PPI2_FS2     (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(2))
+#define P_PPI2_FS1     (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(2))
+#define P_PPI2_CLK     (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(2))
+#define P_CNT_CZM      (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(3))
+
+#define P_UART1_TX     (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(0))
+#define P_UART1_RX     (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(0))
+#define P_ATAPI_RESET  (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(0))
+#define P_HOST_ADDR    (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(0))
+#define P_HOST_ACK     (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(0))
+#define P_MTX  (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(0))
+#define P_MRX  (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(0))
+#define P_MRXONB       (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(0))
+#define P_A4   (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(0))
+#define P_A5   (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(0))
+#define P_A6   (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(0))
+#define P_A7   (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(0))
+#define P_A8   (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(0))
+#define P_A9   (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(0))
+#define P_PPI1_FS3     (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(1))
+#define P_PPI2_FS3     (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(1))
+#define P_TMR8 (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(1))
+#define P_TMR9 (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(1))
+#define P_TMR10        (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(1))
+#define P_DMAR0        (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(1))
+#define P_DMAR1        (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(1))
+#define P_PPI0_FS3     (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(2))
+#define P_CNT_CDG      (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(2))
+#define P_CNT_CUD      (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(2))
+
+#define P_A10  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI0) | P_FUNCT(0))
+#define P_A11  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI1) | P_FUNCT(0))
+#define P_A12  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI2) | P_FUNCT(0))
+#define P_A13  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI3) | P_FUNCT(0))
+#define P_A14  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI4) | P_FUNCT(0))
+#define P_A15  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI5) | P_FUNCT(0))
+#define P_A16  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI6) | P_FUNCT(0))
+#define P_A17  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI7) | P_FUNCT(0))
+#define P_A18  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI8) | P_FUNCT(0))
+#define P_A19  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI9) | P_FUNCT(0))
+#define P_A20  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI10) | P_FUNCT(0))
+#define P_A21  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI11) | P_FUNCT(0))
+#define P_A22  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI12) | P_FUNCT(0))
+#define P_A23  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI13) | P_FUNCT(0))
+#define P_A24  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI14) | P_FUNCT(0))
+#define P_A25  (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI15) | P_FUNCT(0))
+#define P_NOR_CLK      (P_DEFINED | P_IDENT(GPIO_PI15) | P_FUNCT(1))
+
+#define P_AMC_ARDY_NOR_WAIT    (P_DEFINED | P_IDENT(GPIO_PJ0) | P_FUNCT(0))
+#define P_NAND_CE      (P_DEFINED | P_IDENT(GPIO_PJ1) | P_FUNCT(0))
+#define P_NAND_RB      (P_DEFINED | P_IDENT(GPIO_PJ2) | P_FUNCT(0))
+#define P_ATAPI_DIOR   (P_DEFINED | P_IDENT(GPIO_PJ3) | P_FUNCT(0))
+#define P_ATAPI_DIOW   (P_DEFINED | P_IDENT(GPIO_PJ4) | P_FUNCT(0))
+#define P_ATAPI_CS0    (P_DEFINED | P_IDENT(GPIO_PJ5) | P_FUNCT(0))
+#define P_ATAPI_CS1    (P_DEFINED | P_IDENT(GPIO_PJ6) | P_FUNCT(0))
+#define P_ATAPI_DMACK  (P_DEFINED | P_IDENT(GPIO_PJ7) | P_FUNCT(0))
+#define P_ATAPI_DMARQ  (P_DEFINED | P_IDENT(GPIO_PJ8) | P_FUNCT(0))
+#define P_ATAPI_INTRQ  (P_DEFINED | P_IDENT(GPIO_PJ9) | P_FUNCT(0))
+#define P_ATAPI_IORDY  (P_DEFINED | P_IDENT(GPIO_PJ10) | P_FUNCT(0))
+#define P_AMC_BR       (P_DEFINED | P_IDENT(GPIO_PJ11) | P_FUNCT(0))
+#define P_AMC_BG       (P_DEFINED | P_IDENT(GPIO_PJ12) | P_FUNCT(0))
+#define P_AMC_BGH      (P_DEFINED | P_IDENT(GPIO_PJ13) | P_FUNCT(0))
+
+#endif /* _MACH_PORTMUX_H_ */
index b14f872e5703cb781dd74e28bf761c094603eac1..1a8ec9e46922295ecd513de90bd2a608defe534e 100644 (file)
 /* Writing to VR_CTL initiates a PLL relock sequence. */
 static __inline__ void bfin_write_VR_CTL(unsigned int val)
 {
-       unsigned long flags, iwr;
+       unsigned long flags, iwr0, iwr1;
 
        /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr = bfin_read32(SICA_IWR0);
+       iwr0 = bfin_read32(SICA_IWR0);
+       iwr1 = bfin_read32(SICA_IWR1);
        /* Only allow PPL Wakeup) */
        bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+       bfin_write32(SICA_IWR1, 0);
 
        bfin_write16(VR_CTL, val);
        __builtin_bfin_ssync();
@@ -70,7 +72,8 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
        local_irq_save(flags);
        asm("IDLE;");
        local_irq_restore(flags);
-       bfin_write32(SICA_IWR0, iwr);
+       bfin_write32(SICA_IWR0, iwr0);
+       bfin_write32(SICA_IWR1, iwr1);
 }
 #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
index 21d982003e7525c80188ae55bf2df8985ec77658..766334b7d8ab8bf3a225408bb1dc6fe353356714 100644 (file)
@@ -32,4 +32,7 @@
 #define CH_IMEM_STREAM1_SRC    34
 #define CH_IMEM_STREAM1_DEST   35
 
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+
 #endif
diff --git a/include/asm-blackfin/mach-bf561/portmux.h b/include/asm-blackfin/mach-bf561/portmux.h
new file mode 100644 (file)
index 0000000..10d11d5
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_PPI0_CLK     (P_DONTCARE)
+#define P_PPI0_FS1     (P_DONTCARE)
+#define P_PPI0_FS2     (P_DONTCARE)
+#define P_PPI0_FS3     (P_DONTCARE)
+#define P_PPI0_D15     (P_DEFINED | P_IDENT(GPIO_PF47))
+#define P_PPI0_D14     (P_DEFINED | P_IDENT(GPIO_PF46))
+#define P_PPI0_D13     (P_DEFINED | P_IDENT(GPIO_PF45))
+#define P_PPI0_D12     (P_DEFINED | P_IDENT(GPIO_PF44))
+#define P_PPI0_D11     (P_DEFINED | P_IDENT(GPIO_PF43))
+#define P_PPI0_D10     (P_DEFINED | P_IDENT(GPIO_PF42))
+#define P_PPI0_D9      (P_DEFINED | P_IDENT(GPIO_PF41))
+#define P_PPI0_D8      (P_DEFINED | P_IDENT(GPIO_PF40))
+#define P_PPI0_D0      (P_DONTCARE)
+#define P_PPI0_D1      (P_DONTCARE)
+#define P_PPI0_D2      (P_DONTCARE)
+#define P_PPI0_D3      (P_DONTCARE)
+#define P_PPI0_D4      (P_DONTCARE)
+#define P_PPI0_D5      (P_DONTCARE)
+#define P_PPI0_D6      (P_DONTCARE)
+#define P_PPI0_D7      (P_DONTCARE)
+#define P_PPI1_CLK     (P_DONTCARE)
+#define P_PPI1_FS1     (P_DONTCARE)
+#define P_PPI1_FS2     (P_DONTCARE)
+#define P_PPI1_FS3     (P_DONTCARE)
+#define P_PPI1_D15     (P_DEFINED | P_IDENT(GPIO_PF39))
+#define P_PPI1_D14     (P_DEFINED | P_IDENT(GPIO_PF38))
+#define P_PPI1_D13     (P_DEFINED | P_IDENT(GPIO_PF37))
+#define P_PPI1_D12     (P_DEFINED | P_IDENT(GPIO_PF36))
+#define P_PPI1_D11     (P_DEFINED | P_IDENT(GPIO_PF35))
+#define P_PPI1_D10     (P_DEFINED | P_IDENT(GPIO_PF34))
+#define P_PPI1_D9      (P_DEFINED | P_IDENT(GPIO_PF33))
+#define P_PPI1_D8      (P_DEFINED | P_IDENT(GPIO_PF32))
+#define P_PPI1_D0      (P_DONTCARE)
+#define P_PPI1_D1      (P_DONTCARE)
+#define P_PPI1_D2      (P_DONTCARE)
+#define P_PPI1_D3      (P_DONTCARE)
+#define P_PPI1_D4      (P_DONTCARE)
+#define P_PPI1_D5      (P_DONTCARE)
+#define P_PPI1_D6      (P_DONTCARE)
+#define P_PPI1_D7      (P_DONTCARE)
+#define P_SPORT1_TSCLK (P_DEFINED | P_IDENT(GPIO_PF31))
+#define P_SPORT1_RSCLK (P_DEFINED | P_IDENT(GPIO_PF30))
+#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(GPIO_PF29))
+#define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PF28))
+#define P_UART0_RX     (P_DEFINED | P_IDENT(GPIO_PF27))
+#define P_UART0_TX     (P_DEFINED | P_IDENT(GPIO_PF26))
+#define P_SPORT1_DRSEC (P_DEFINED | P_IDENT(GPIO_PF25))
+#define P_SPORT1_RFS   (P_DEFINED | P_IDENT(GPIO_PF24))
+#define P_SPORT1_DTPRI (P_DEFINED | P_IDENT(GPIO_PF23))
+#define P_SPORT1_DTSEC (P_DEFINED | P_IDENT(GPIO_PF22))
+#define P_SPORT1_TFS   (P_DEFINED | P_IDENT(GPIO_PF21))
+#define P_SPORT1_DRPRI (P_DONTCARE)
+#define P_SPORT0_DRSEC (P_DEFINED | P_IDENT(GPIO_PF20))
+#define P_SPORT0_RFS   (P_DEFINED | P_IDENT(GPIO_PF19))
+#define P_SPORT0_DTPRI (P_DEFINED | P_IDENT(GPIO_PF18))
+#define P_SPORT0_DTSEC (P_DEFINED | P_IDENT(GPIO_PF17))
+#define P_SPORT0_TFS   (P_DEFINED | P_IDENT(GPIO_PF16))
+#define P_SPORT0_DRPRI (P_DONTCARE)
+#define P_TMRCLK       (P_DEFINED | P_IDENT(GPIO_PF15))
+#define P_SPI0_SSEL7   (P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_SPI0_SSEL6   (P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_SPI0_SSEL5   (P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_SPI0_SSEL4   (P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_SPI0_SSEL3   (P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_SPI0_SSEL2   (P_DEFINED | P_IDENT(GPIO_PF2))
+#define P_SPI0_SSEL1   (P_DEFINED | P_IDENT(GPIO_PF1))
+#define P_SPI0_SS      (P_DEFINED | P_IDENT(GPIO_PF0))
+#define P_TMR11                (P_DONTCARE)
+#define P_TMR10                (P_DONTCARE)
+#define P_TMR9         (P_DONTCARE)
+#define P_TMR8         (P_DONTCARE)
+#define P_TMR7         (P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_TMR6         (P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_TMR5         (P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_TMR4         (P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_TMR3         (P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_TMR2         (P_DEFINED | P_IDENT(GPIO_PF2))
+#define P_TMR1         (P_DEFINED | P_IDENT(GPIO_PF1))
+#define P_TMR0         (P_DEFINED | P_IDENT(GPIO_PF0))
+#define P_SPI0_MOSI    (P_DONTCARE)
+#define P_SPI0_MIS0    (P_DONTCARE)
+#define P_SPI0_SCK     (P_DONTCARE)
+
+#endif /* _MACH_PORTMUX_H_ */
index 58f878947cbc171f3b8e0c824c39cbf100e9d10c..94ed381e560671b74374584b5d6459b4f8d0c426 100644 (file)
 #define bfin_write_SRAM_BASE_ADDRESS(val)    bfin_write32(SRAM_BASE_ADDRESS,val)
 #define bfin_read_DMEM_CONTROL()             bfin_read32(DMEM_CONTROL)
 #ifdef ANOMALY_05000125
-static __inline__ void bfin_write_DMEM_CONTROL(unsigned int val)
-{
-       unsigned long flags, iwr;
-
-       local_irq_save(flags);
-       __asm__(".align 8\n");
-       bfin_write32(IMEM_CONTROL, val);
-       __builtin_bfin_ssync();
-       local_irq_restore(flags);
-}
+extern void bfin_write_DMEM_CONTROL(unsigned int val);
 #else
 #define bfin_write_DMEM_CONTROL(val)         bfin_write32(DMEM_CONTROL,val)
 #endif
@@ -139,17 +130,7 @@ static __inline__ void bfin_write_DMEM_CONTROL(unsigned int val)
 */
 #define bfin_read_IMEM_CONTROL()             bfin_read32(IMEM_CONTROL)
 #ifdef ANOMALY_05000125
-static __inline__ void bfin_write_IMEM_CONTROL(unsigned int val)
-{
-       unsigned long flags, iwr;
-
-       local_irq_save(flags);
-       __asm__(".align 8\n");
-       bfin_write32(IMEM_CONTROL, val);
-       __builtin_bfin_ssync();
-       local_irq_restore(flags);
-
-}
+extern void bfin_write_IMEM_CONTROL(unsigned int val);
 #else
 #define bfin_write_IMEM_CONTROL(val)         bfin_write32(IMEM_CONTROL,val)
 #endif
index 4d504f908c0ce80867de94ab9f84050dfdeaf702..b58f5ad3f024bed59d328d9773b7675537a23fe0 100644 (file)
@@ -22,8 +22,6 @@
 #define MAP_NORESERVE  0x4000  /* don't check for reservations */
 #define MAP_POPULATE   0x8000  /* populate (prefault) pagetables */
 #define MAP_NONBLOCK   0x10000 /* do not block on IO */
-#define MAP_UNINITIALIZE 0x4000000  /* For anonymous mmap, memory could
-                                    be uninitialized. */
 
 #define MS_ASYNC       1       /* sync memory asynchronously */
 #define MS_INVALIDATE  2       /* invalidate the caches */
index ffad947f1b2a9c7884f7fea9efd65dedf82f64b7..8bc86717021c111452337c3812f259c8985129fa 100644 (file)
@@ -4,7 +4,11 @@
 /* PAGE_SHIFT determines the page size */
 
 #define PAGE_SHIFT     12
+#ifdef __ASSEMBLY__
+#define PAGE_SIZE      (1 << PAGE_SHIFT)
+#else
 #define PAGE_SIZE      (1UL << PAGE_SHIFT)
+#endif
 #define PAGE_MASK      (~(PAGE_SIZE-1))
 
 #ifdef __KERNEL__
diff --git a/include/asm-blackfin/portmux.h b/include/asm-blackfin/portmux.h
new file mode 100644 (file)
index 0000000..9d3681e
--- /dev/null
@@ -0,0 +1,1133 @@
+/*
+ * Common header file for blackfin family of processors.
+ *
+ */
+
+#ifndef _PORTMUX_H_
+#define _PORTMUX_H_
+
+#define P_IDENT(x)     ((x) & 0x1FF)
+#define P_FUNCT(x)     (((x) & 0x3) << 9)
+#define P_FUNCT2MUX(x) (((x) >> 9) & 0x3)
+#define P_DEFINED      0x8000
+#define P_UNDEF                0x4000
+#define P_MAYSHARE     0x2000
+#define P_DONTCARE     0x1000
+
+#include <asm/gpio.h>
+#include <asm/mach/portmux.h>
+
+#ifndef P_SPORT2_TFS
+#define P_SPORT2_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DTSEC
+#define P_SPORT2_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DTPRI
+#define P_SPORT2_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT2_TSCLK
+#define P_SPORT2_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT2_RFS
+#define P_SPORT2_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DRSEC
+#define P_SPORT2_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DRPRI
+#define P_SPORT2_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT2_RSCLK
+#define P_SPORT2_RSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT3_TFS
+#define P_SPORT3_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DTSEC
+#define P_SPORT3_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DTPRI
+#define P_SPORT3_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT3_TSCLK
+#define P_SPORT3_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT3_RFS
+#define P_SPORT3_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DRSEC
+#define P_SPORT3_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DRPRI
+#define P_SPORT3_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT3_RSCLK
+#define P_SPORT3_RSCLK P_UNDEF
+#endif
+
+#ifndef P_TMR4
+#define P_TMR4 P_UNDEF
+#endif
+
+#ifndef P_TMR5
+#define P_TMR5 P_UNDEF
+#endif
+
+#ifndef P_TMR6
+#define P_TMR6 P_UNDEF
+#endif
+
+#ifndef P_TMR7
+#define P_TMR7 P_UNDEF
+#endif
+
+#ifndef P_TWI1_SCL
+#define P_TWI1_SCL P_UNDEF
+#endif
+
+#ifndef P_TWI1_SDA
+#define P_TWI1_SDA P_UNDEF
+#endif
+
+#ifndef P_UART3_RTS
+#define P_UART3_RTS P_UNDEF
+#endif
+
+#ifndef P_UART3_CTS
+#define P_UART3_CTS P_UNDEF
+#endif
+
+#ifndef P_UART2_TX
+#define P_UART2_TX P_UNDEF
+#endif
+
+#ifndef P_UART2_RX
+#define P_UART2_RX P_UNDEF
+#endif
+
+#ifndef P_UART3_TX
+#define P_UART3_TX P_UNDEF
+#endif
+
+#ifndef P_UART3_RX
+#define P_UART3_RX P_UNDEF
+#endif
+
+#ifndef P_SPI2_SS
+#define P_SPI2_SS P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL1
+#define P_SPI2_SSEL1 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL2
+#define P_SPI2_SSEL2 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL3
+#define P_SPI2_SSEL3 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SCK
+#define P_SPI2_SCK P_UNDEF
+#endif
+
+#ifndef P_SPI2_MOSI
+#define P_SPI2_MOSI P_UNDEF
+#endif
+
+#ifndef P_SPI2_MISO
+#define P_SPI2_MISO P_UNDEF
+#endif
+
+#ifndef P_TMR0
+#define P_TMR0 P_UNDEF
+#endif
+
+#ifndef P_TMR1
+#define P_TMR1 P_UNDEF
+#endif
+
+#ifndef P_TMR2
+#define P_TMR2 P_UNDEF
+#endif
+
+#ifndef P_TMR3
+#define P_TMR3 P_UNDEF
+#endif
+
+#ifndef P_SPORT0_TFS
+#define P_SPORT0_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DTSEC
+#define P_SPORT0_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DTPRI
+#define P_SPORT0_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT0_TSCLK
+#define P_SPORT0_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT0_RFS
+#define P_SPORT0_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DRSEC
+#define P_SPORT0_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DRPRI
+#define P_SPORT0_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT0_RSCLK
+#define P_SPORT0_RSCLK P_UNDEF
+#endif
+
+#ifndef P_SD_D0
+#define P_SD_D0 P_UNDEF
+#endif
+
+#ifndef P_SD_D1
+#define P_SD_D1 P_UNDEF
+#endif
+
+#ifndef P_SD_D2
+#define P_SD_D2 P_UNDEF
+#endif
+
+#ifndef P_SD_D3
+#define P_SD_D3 P_UNDEF
+#endif
+
+#ifndef P_SD_CLK
+#define P_SD_CLK P_UNDEF
+#endif
+
+#ifndef P_SD_CMD
+#define P_SD_CMD P_UNDEF
+#endif
+
+#ifndef P_MMCLK
+#define P_MMCLK P_UNDEF
+#endif
+
+#ifndef P_MBCLK
+#define P_MBCLK P_UNDEF
+#endif
+
+#ifndef P_PPI1_D0
+#define P_PPI1_D0 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D1
+#define P_PPI1_D1 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D2
+#define P_PPI1_D2 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D3
+#define P_PPI1_D3 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D4
+#define P_PPI1_D4 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D5
+#define P_PPI1_D5 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D6
+#define P_PPI1_D6 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D7
+#define P_PPI1_D7 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D8
+#define P_PPI1_D8 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D9
+#define P_PPI1_D9 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D10
+#define P_PPI1_D10 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D11
+#define P_PPI1_D11 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D12
+#define P_PPI1_D12 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D13
+#define P_PPI1_D13 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D14
+#define P_PPI1_D14 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D15
+#define P_PPI1_D15 P_UNDEF
+#endif
+
+#ifndef P_HOST_D8
+#define P_HOST_D8 P_UNDEF
+#endif
+
+#ifndef P_HOST_D9
+#define P_HOST_D9 P_UNDEF
+#endif
+
+#ifndef P_HOST_D10
+#define P_HOST_D10 P_UNDEF
+#endif
+
+#ifndef P_HOST_D11
+#define P_HOST_D11 P_UNDEF
+#endif
+
+#ifndef P_HOST_D12
+#define P_HOST_D12 P_UNDEF
+#endif
+
+#ifndef P_HOST_D13
+#define P_HOST_D13 P_UNDEF
+#endif
+
+#ifndef P_HOST_D14
+#define P_HOST_D14 P_UNDEF
+#endif
+
+#ifndef P_HOST_D15
+#define P_HOST_D15 P_UNDEF
+#endif
+
+#ifndef P_HOST_D0
+#define P_HOST_D0 P_UNDEF
+#endif
+
+#ifndef P_HOST_D1
+#define P_HOST_D1 P_UNDEF
+#endif
+
+#ifndef P_HOST_D2
+#define P_HOST_D2 P_UNDEF
+#endif
+
+#ifndef P_HOST_D3
+#define P_HOST_D3 P_UNDEF
+#endif
+
+#ifndef P_HOST_D4
+#define P_HOST_D4 P_UNDEF
+#endif
+
+#ifndef P_HOST_D5
+#define P_HOST_D5 P_UNDEF
+#endif
+
+#ifndef P_HOST_D6
+#define P_HOST_D6 P_UNDEF
+#endif
+
+#ifndef P_HOST_D7
+#define P_HOST_D7 P_UNDEF
+#endif
+
+#ifndef P_SPORT1_TFS
+#define P_SPORT1_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DTSEC
+#define P_SPORT1_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DTPRI
+#define P_SPORT1_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT1_TSCLK
+#define P_SPORT1_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT1_RFS
+#define P_SPORT1_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DRSEC
+#define P_SPORT1_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DRPRI
+#define P_SPORT1_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT1_RSCLK
+#define P_SPORT1_RSCLK P_UNDEF
+#endif
+
+#ifndef P_PPI2_D0
+#define P_PPI2_D0 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D1
+#define P_PPI2_D1 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D2
+#define P_PPI2_D2 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D3
+#define P_PPI2_D3 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D4
+#define P_PPI2_D4 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D5
+#define P_PPI2_D5 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D6
+#define P_PPI2_D6 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D7
+#define P_PPI2_D7 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D18
+#define P_PPI0_D18 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D19
+#define P_PPI0_D19 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D20
+#define P_PPI0_D20 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D21
+#define P_PPI0_D21 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D22
+#define P_PPI0_D22 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D23
+#define P_PPI0_D23 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW0
+#define P_KEY_ROW0 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW1
+#define P_KEY_ROW1 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW2
+#define P_KEY_ROW2 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW3
+#define P_KEY_ROW3 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL0
+#define P_KEY_COL0 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL1
+#define P_KEY_COL1 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL2
+#define P_KEY_COL2 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL3
+#define P_KEY_COL3 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SCK
+#define P_SPI0_SCK P_UNDEF
+#endif
+
+#ifndef P_SPI0_MISO
+#define P_SPI0_MISO P_UNDEF
+#endif
+
+#ifndef P_SPI0_MOSI
+#define P_SPI0_MOSI P_UNDEF
+#endif
+
+#ifndef P_SPI0_SS
+#define P_SPI0_SS P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL1
+#define P_SPI0_SSEL1 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL2
+#define P_SPI0_SSEL2 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL3
+#define P_SPI0_SSEL3 P_UNDEF
+#endif
+
+#ifndef P_UART0_TX
+#define P_UART0_TX P_UNDEF
+#endif
+
+#ifndef P_UART0_RX
+#define P_UART0_RX P_UNDEF
+#endif
+
+#ifndef P_UART1_RTS
+#define P_UART1_RTS P_UNDEF
+#endif
+
+#ifndef P_UART1_CTS
+#define P_UART1_CTS P_UNDEF
+#endif
+
+#ifndef P_PPI1_CLK
+#define P_PPI1_CLK P_UNDEF
+#endif
+
+#ifndef P_PPI1_FS1
+#define P_PPI1_FS1 P_UNDEF
+#endif
+
+#ifndef P_PPI1_FS2
+#define P_PPI1_FS2 P_UNDEF
+#endif
+
+#ifndef P_TWI0_SCL
+#define P_TWI0_SCL P_UNDEF
+#endif
+
+#ifndef P_TWI0_SDA
+#define P_TWI0_SDA P_UNDEF
+#endif
+
+#ifndef P_KEY_COL7
+#define P_KEY_COL7 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW6
+#define P_KEY_ROW6 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL6
+#define P_KEY_COL6 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW5
+#define P_KEY_ROW5 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL5
+#define P_KEY_COL5 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW4
+#define P_KEY_ROW4 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL4
+#define P_KEY_COL4 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW7
+#define P_KEY_ROW7 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D0
+#define P_PPI0_D0 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D1
+#define P_PPI0_D1 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D2
+#define P_PPI0_D2 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D3
+#define P_PPI0_D3 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D4
+#define P_PPI0_D4 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D5
+#define P_PPI0_D5 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D6
+#define P_PPI0_D6 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D7
+#define P_PPI0_D7 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D8
+#define P_PPI0_D8 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D9
+#define P_PPI0_D9 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D10
+#define P_PPI0_D10 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D11
+#define P_PPI0_D11 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D12
+#define P_PPI0_D12 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D13
+#define P_PPI0_D13 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D14
+#define P_PPI0_D14 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D15
+#define P_PPI0_D15 P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D0A
+#define P_ATAPI_D0A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D1A
+#define P_ATAPI_D1A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D2A
+#define P_ATAPI_D2A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D3A
+#define P_ATAPI_D3A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D4A
+#define P_ATAPI_D4A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D5A
+#define P_ATAPI_D5A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D6A
+#define P_ATAPI_D6A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D7A
+#define P_ATAPI_D7A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D8A
+#define P_ATAPI_D8A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D9A
+#define P_ATAPI_D9A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D10A
+#define P_ATAPI_D10A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D11A
+#define P_ATAPI_D11A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D12A
+#define P_ATAPI_D12A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D13A
+#define P_ATAPI_D13A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D14A
+#define P_ATAPI_D14A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D15A
+#define P_ATAPI_D15A P_UNDEF
+#endif
+
+#ifndef P_PPI0_CLK
+#define P_PPI0_CLK P_UNDEF
+#endif
+
+#ifndef P_PPI0_FS1
+#define P_PPI0_FS1 P_UNDEF
+#endif
+
+#ifndef P_PPI0_FS2
+#define P_PPI0_FS2 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D16
+#define P_PPI0_D16 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D17
+#define P_PPI0_D17 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL1
+#define P_SPI1_SSEL1 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL2
+#define P_SPI1_SSEL2 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL3
+#define P_SPI1_SSEL3 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SCK
+#define P_SPI1_SCK P_UNDEF
+#endif
+
+#ifndef P_SPI1_MISO
+#define P_SPI1_MISO P_UNDEF
+#endif
+
+#ifndef P_SPI1_MOSI
+#define P_SPI1_MOSI P_UNDEF
+#endif
+
+#ifndef P_SPI1_SS
+#define P_SPI1_SS P_UNDEF
+#endif
+
+#ifndef P_CAN0_TX
+#define P_CAN0_TX P_UNDEF
+#endif
+
+#ifndef P_CAN0_RX
+#define P_CAN0_RX P_UNDEF
+#endif
+
+#ifndef P_CAN1_TX
+#define P_CAN1_TX P_UNDEF
+#endif
+
+#ifndef P_CAN1_RX
+#define P_CAN1_RX P_UNDEF
+#endif
+
+#ifndef P_ATAPI_A0A
+#define P_ATAPI_A0A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_A1A
+#define P_ATAPI_A1A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_A2A
+#define P_ATAPI_A2A P_UNDEF
+#endif
+
+#ifndef P_HOST_CE
+#define P_HOST_CE P_UNDEF
+#endif
+
+#ifndef P_HOST_RD
+#define P_HOST_RD P_UNDEF
+#endif
+
+#ifndef P_HOST_WR
+#define P_HOST_WR P_UNDEF
+#endif
+
+#ifndef P_MTXONB
+#define P_MTXONB P_UNDEF
+#endif
+
+#ifndef P_PPI2_FS2
+#define P_PPI2_FS2 P_UNDEF
+#endif
+
+#ifndef P_PPI2_FS1
+#define P_PPI2_FS1 P_UNDEF
+#endif
+
+#ifndef P_PPI2_CLK
+#define P_PPI2_CLK P_UNDEF
+#endif
+
+#ifndef P_CNT_CZM
+#define P_CNT_CZM P_UNDEF
+#endif
+
+#ifndef P_UART1_TX
+#define P_UART1_TX P_UNDEF
+#endif
+
+#ifndef P_UART1_RX
+#define P_UART1_RX P_UNDEF
+#endif
+
+#ifndef P_ATAPI_RESET
+#define P_ATAPI_RESET P_UNDEF
+#endif
+
+#ifndef P_HOST_ADDR
+#define P_HOST_ADDR P_UNDEF
+#endif
+
+#ifndef P_HOST_ACK
+#define P_HOST_ACK P_UNDEF
+#endif
+
+#ifndef P_MTX
+#define P_MTX P_UNDEF
+#endif
+
+#ifndef P_MRX
+#define P_MRX P_UNDEF
+#endif
+
+#ifndef P_MRXONB
+#define P_MRXONB P_UNDEF
+#endif
+
+#ifndef P_A4
+#define P_A4 P_UNDEF
+#endif
+
+#ifndef P_A5
+#define P_A5 P_UNDEF
+#endif
+
+#ifndef P_A6
+#define P_A6 P_UNDEF
+#endif
+
+#ifndef P_A7
+#define P_A7 P_UNDEF
+#endif
+
+#ifndef P_A8
+#define P_A8 P_UNDEF
+#endif
+
+#ifndef P_A9
+#define P_A9 P_UNDEF
+#endif
+
+#ifndef P_PPI1_FS3
+#define P_PPI1_FS3 P_UNDEF
+#endif
+
+#ifndef P_PPI2_FS3
+#define P_PPI2_FS3 P_UNDEF
+#endif
+
+#ifndef P_TMR8
+#define P_TMR8 P_UNDEF
+#endif
+
+#ifndef P_TMR9
+#define P_TMR9 P_UNDEF
+#endif
+
+#ifndef P_TMR10
+#define P_TMR10 P_UNDEF
+#endif
+#ifndef P_TMR11
+#define P_TMR11 P_UNDEF
+#endif
+
+#ifndef P_DMAR0
+#define P_DMAR0 P_UNDEF
+#endif
+
+#ifndef P_DMAR1
+#define P_DMAR1 P_UNDEF
+#endif
+
+#ifndef P_PPI0_FS3
+#define P_PPI0_FS3 P_UNDEF
+#endif
+
+#ifndef P_CNT_CDG
+#define P_CNT_CDG P_UNDEF
+#endif
+
+#ifndef P_CNT_CUD
+#define P_CNT_CUD P_UNDEF
+#endif
+
+#ifndef P_A10
+#define P_A10 P_UNDEF
+#endif
+
+#ifndef P_A11
+#define P_A11 P_UNDEF
+#endif
+
+#ifndef P_A12
+#define P_A12 P_UNDEF
+#endif
+
+#ifndef P_A13
+#define P_A13 P_UNDEF
+#endif
+
+#ifndef P_A14
+#define P_A14 P_UNDEF
+#endif
+
+#ifndef P_A15
+#define P_A15 P_UNDEF
+#endif
+
+#ifndef P_A16
+#define P_A16 P_UNDEF
+#endif
+
+#ifndef P_A17
+#define P_A17 P_UNDEF
+#endif
+
+#ifndef P_A18
+#define P_A18 P_UNDEF
+#endif
+
+#ifndef P_A19
+#define P_A19 P_UNDEF
+#endif
+
+#ifndef P_A20
+#define P_A20 P_UNDEF
+#endif
+
+#ifndef P_A21
+#define P_A21 P_UNDEF
+#endif
+
+#ifndef P_A22
+#define P_A22 P_UNDEF
+#endif
+
+#ifndef P_A23
+#define P_A23 P_UNDEF
+#endif
+
+#ifndef P_A24
+#define P_A24 P_UNDEF
+#endif
+
+#ifndef P_A25
+#define P_A25 P_UNDEF
+#endif
+
+#ifndef P_NOR_CLK
+#define P_NOR_CLK P_UNDEF
+#endif
+
+#ifndef  P_TMRCLK
+#define  P_TMRCLK P_UNDEF
+#endif
+
+#ifndef P_AMC_ARDY_NOR_WAIT
+#define P_AMC_ARDY_NOR_WAIT P_UNDEF
+#endif
+
+#ifndef P_NAND_CE
+#define P_NAND_CE P_UNDEF
+#endif
+
+#ifndef P_NAND_RB
+#define P_NAND_RB P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DIOR
+#define P_ATAPI_DIOR P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DIOW
+#define P_ATAPI_DIOW P_UNDEF
+#endif
+
+#ifndef P_ATAPI_CS0
+#define P_ATAPI_CS0 P_UNDEF
+#endif
+
+#ifndef P_ATAPI_CS1
+#define P_ATAPI_CS1 P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DMACK
+#define P_ATAPI_DMACK P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DMARQ
+#define P_ATAPI_DMARQ P_UNDEF
+#endif
+
+#ifndef P_ATAPI_INTRQ
+#define P_ATAPI_INTRQ P_UNDEF
+#endif
+
+#ifndef P_ATAPI_IORDY
+#define P_ATAPI_IORDY P_UNDEF
+#endif
+
+#ifndef P_AMC_BR
+#define P_AMC_BR P_UNDEF
+#endif
+
+#ifndef P_AMC_BG
+#define P_AMC_BG P_UNDEF
+#endif
+
+#ifndef P_AMC_BGH
+#define P_AMC_BGH P_UNDEF
+#endif
+
+/* EMAC */
+
+#ifndef P_MII0_ETxD0
+#define P_MII0_ETxD0 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxD1
+#define P_MII0_ETxD1 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxD2
+#define P_MII0_ETxD2 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxD3
+#define P_MII0_ETxD3 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxEN
+#define P_MII0_ETxEN P_UNDEF
+#endif
+
+#ifndef P_MII0_TxCLK
+#define P_MII0_TxCLK P_UNDEF
+#endif
+
+#ifndef P_MII0_PHYINT
+#define P_MII0_PHYINT P_UNDEF
+#endif
+
+#ifndef P_MII0_COL
+#define P_MII0_COL P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD0
+#define P_MII0_ERxD0 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD1
+#define P_MII0_ERxD1 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD2
+#define P_MII0_ERxD2 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD3
+#define P_MII0_ERxD3 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxDV
+#define P_MII0_ERxDV P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxCLK
+#define P_MII0_ERxCLK P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxER
+#define P_MII0_ERxER P_UNDEF
+#endif
+
+#ifndef P_MII0_CRS
+#define P_MII0_CRS P_UNDEF
+#endif
+
+#ifndef P_RMII0_REF_CLK
+#define P_RMII0_REF_CLK P_UNDEF
+#endif
+
+#ifndef P_RMII0_MDINT
+#define P_RMII0_MDINT P_UNDEF
+#endif
+
+#ifndef P_RMII0_CRS_DV
+#define P_RMII0_CRS_DV P_UNDEF
+#endif
+
+#ifndef P_MDC
+#define P_MDC P_UNDEF
+#endif
+
+#ifndef P_MDIO
+#define P_MDIO P_UNDEF
+#endif
+
+#endif                         /* _PORTMUX_H_ */
diff --git a/include/asm-blackfin/trace.h b/include/asm-blackfin/trace.h
new file mode 100644 (file)
index 0000000..9c2474c
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Common header file for blackfin family of processors.
+ *
+ */
+
+#ifndef _BLACKFIN_TRACE_
+#define _BLACKFIN_TRACE_
+
+#ifndef __ASSEMBLY__
+/* Trace Macros for C files */
+
+#define trace_buffer_save(x) \
+        do { \
+                (x) = bfin_read_TBUFCTL(); \
+                bfin_write_TBUFCTL((x) & ~TBUFEN); \
+        } while (0)
+
+#define trace_buffer_restore(x) \
+        do { \
+                bfin_write_TBUFCTL((x));        \
+        } while (0)
+
+#else
+/* Trace Macros for Assembly files */
+
+#define TRACE_BUFFER_START(preg, dreg) trace_buffer_start(preg, dreg)
+#define TRACE_BUFFER_STOP(preg, dreg)  trace_buffer_stop(preg, dreg)
+
+#define trace_buffer_stop(preg, dreg)  \
+       preg.L = LO(TBUFCTL);           \
+       preg.H = HI(TBUFCTL);           \
+       dreg = 0x1;                     \
+       [preg] = dreg;
+
+#define trace_buffer_start(preg, dreg) \
+       preg.L = LO(TBUFCTL);           \
+       preg.H = HI(TBUFCTL);           \
+       dreg = 0x13;                    \
+       [preg] = dreg;
+
+#ifdef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
+# define DEBUG_START_HWTRACE(preg, dreg) trace_buffer_start(preg, dreg)
+# define DEBUG_STOP_HWTRACE(preg, dreg) trace_buffer_stop(preg, dreg)
+
+#else
+# define DEBUG_START_HWTRACE(preg, dreg)
+# define DEBUG_STOP_HWTRACE(preg, dreg)
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif                         /* _BLACKFIN_TRACE_ */
index b2ac8a331da1f9d17fdaf7c60a80b4b9a6ba895b..730ce40fdd0fca1674e220abd4ffe75d10304339 100644 (file)
@@ -52,47 +52,11 @@ struct pci_dev;
 #define pci_unmap_len(PTR, LEN_NAME)           (0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
 
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask)   (1)
-
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
-       return ((dma64_addr_t) page_to_phys(page) +
-               (dma64_addr_t) offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-       return pfn_to_page(dma_addr >> PAGE_SHIFT);
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-       return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                               enum pci_mmap_state mmap_state, int write_combine);
 
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
 
 /* implement the pci_ DMA API in terms of the generic device dma_ one */
index f35a4511e7b91c7a0f815b911678f13edc891005..585d9b49949a7537d9d1f89221f93c047cfedacf 100644 (file)
@@ -22,10 +22,6 @@ struct pci_dev;
 
 #define pcibios_assign_all_busses()    0
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 extern void pcibios_set_master(struct pci_dev *dev);
 
 extern void pcibios_penalize_isa_irq(int irq);
@@ -44,9 +40,6 @@ extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
 extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
                                void *vaddr, dma_addr_t dma_handle);
 
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask)   (1)
-
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_controller_num(PDEV)       (0)
 
index 0c771b05fdd5db25bdb6210aa28fb0457f25c950..97389b35aa3540f0fbd734afe9fc30c0d61c76de 100644 (file)
@@ -22,8 +22,4 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
 
 #define PCI_DMA_BUS_IS_PHYS    (1)
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* _ASM_H8300_PCI_H */
index bd024ab4fe53b02f6e9b0fe678defb0d1a982242..ed8affbf96cb804f3a97ec46d610fdec19345a2b 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _LINUX_BOOT_H
-#define _LINUX_BOOT_H
+#ifndef _ASM_BOOT_H
+#define _ASM_BOOT_H
 
 /* Don't touch these, unless you really know what you're doing. */
 #define DEF_INITSEG    0x9000
@@ -17,4 +17,4 @@
                                + (CONFIG_PHYSICAL_ALIGN - 1)) \
                                & ~(CONFIG_PHYSICAL_ALIGN - 1))
 
-#endif /* _LINUX_BOOT_H */
+#endif /* _ASM_BOOT_H */
diff --git a/include/asm-i386/bootparam.h b/include/asm-i386/bootparam.h
new file mode 100644 (file)
index 0000000..427d865
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef _ASM_BOOTPARAM_H
+#define _ASM_BOOTPARAM_H
+
+#include <linux/types.h>
+#include <linux/screen_info.h>
+#include <linux/apm_bios.h>
+#include <asm/e820.h>
+#include <linux/edd.h>
+#include <video/edid.h>
+
+struct setup_header {
+       u8      setup_sects;
+       u16     root_flags;
+       u32     syssize;
+       u16     ram_size;
+       u16     vid_mode;
+       u16     root_dev;
+       u16     boot_flag;
+       u16     jump;
+       u32     header;
+       u16     version;
+       u32     realmode_swtch;
+       u16     start_sys;
+       u16     kernel_version;
+       u8      type_of_loader;
+       u8      loadflags;
+#define LOADED_HIGH    0x01
+#define CAN_USE_HEAP   0x80
+       u16     setup_move_size;
+       u32     code32_start;
+       u32     ramdisk_image;
+       u32     ramdisk_size;
+       u32     bootsect_kludge;
+       u16     heap_end_ptr;
+       u16     _pad1;
+       u32     cmd_line_ptr;
+       u32     initrd_addr_max;
+       u32     kernel_alignment;
+       u8      relocatable_kernel;
+} __attribute__((packed));
+
+struct sys_desc_table {
+       u16 length;
+       u8  table[14];
+};
+
+struct efi_info {
+       u32 _pad1;
+       u32 efi_systab;
+       u32 efi_memdesc_size;
+       u32 efi_memdec_version;
+       u32 efi_memmap;
+       u32 fi_memmap_size;
+       u32 _pad2[2];
+};
+
+/* The so-called "zeropage" */
+struct boot_params {
+       struct screen_info screen_info;                 /* 0x000 */
+       struct apm_bios_info apm_bios_info;             /* 0x040 */
+       u8  _pad2[12];                                  /* 0x054 */
+       u32 speedstep_info[4];                          /* 0x060 */
+       u8  _pad3[16];                                  /* 0x070 */
+       u8  hd0_info[16];       /* obsolete! */         /* 0x080 */
+       u8  hd1_info[16];       /* obsolete! */         /* 0x090 */
+       struct sys_desc_table sys_desc_table;           /* 0x0a0 */
+       u8  _pad4[144];                                 /* 0x0b0 */
+       struct edid_info edid_info;                     /* 0x140 */
+       struct efi_info efi_info;                       /* 0x1c0 */
+       u32 alt_mem_k;                                  /* 0x1e0 */
+       u32 scratch;            /* Scratch field! */    /* 0x1e4 */
+       u8  e820_entries;                               /* 0x1e8 */
+       u8  eddbuf_entries;                             /* 0x1e9 */
+       u8  edd_mbr_sig_buf_entries;                    /* 0x1ea */
+       u8  _pad6[6];                                   /* 0x1eb */
+       struct setup_header hdr;    /* setup header */  /* 0x1f1 */
+       u8  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
+       u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];        /* 0x290 */
+       struct e820entry e820_map[E820MAX];             /* 0x2d0 */
+       u8  _pad8[48];                                  /* 0xcd0 */
+       struct edd_info eddbuf[EDDMAXNR];               /* 0xd00 */
+       u8  _pad9[276];                                 /* 0xeec */
+} __attribute__((packed));
+
+#endif /* _ASM_BOOTPARAM_H */
index f514e906643a2ae4df0f77baca83c586db24d210..c961c03cf1e2c8b451a0a6d67f0420ec3ee3674e 100644 (file)
@@ -12,7 +12,7 @@
 #endif
 #include <asm/required-features.h>
 
-#define NCAPINTS       7       /* N 32-bit words worth of info */
+#define NCAPINTS       8       /* N 32-bit words worth of info */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
 #define X86_FEATURE_FPU                (0*32+ 0) /* Onboard FPU */
@@ -81,6 +81,7 @@
 #define X86_FEATURE_BTS                (3*32+13)  /* Branch Trace Store */
 #define X86_FEATURE_LAPIC_TIMER_BROKEN (3*32+ 14) /* lapic timer broken in C1 */
 #define X86_FEATURE_SYNC_RDTSC (3*32+15)  /* RDTSC synchronizes the CPU */
+#define X86_FEATURE_REP_GOOD   (3*32+16) /* rep microcode works well on this CPU */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3       (4*32+ 0) /* Streaming SIMD Extensions-3 */
 #define X86_FEATURE_LAHF_LM    (6*32+ 0) /* LAHF/SAHF in long mode */
 #define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */
 
-#define cpu_has(c, bit)                                        \
-       ((__builtin_constant_p(bit) && (bit) < 32 &&    \
-               (1UL << (bit)) & REQUIRED_MASK1) ?      \
-               1 :                                     \
-       test_bit(bit, (c)->x86_capability))
+/*
+ * Auxiliary flags: Linux defined - For features scattered in various
+ * CPUID levels like 0x6, 0xA etc
+ */
+#define X86_FEATURE_IDA                (7*32+ 0) /* Intel Dynamic Acceleration */
+
+#define cpu_has(c, bit)                                                        \
+       (__builtin_constant_p(bit) &&                                   \
+        ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) ||     \
+          (((bit)>>5)==1 && (1UL<<((bit)&31) & REQUIRED_MASK1)) ||     \
+          (((bit)>>5)==2 && (1UL<<((bit)&31) & REQUIRED_MASK2)) ||     \
+          (((bit)>>5)==3 && (1UL<<((bit)&31) & REQUIRED_MASK3)) ||     \
+          (((bit)>>5)==4 && (1UL<<((bit)&31) & REQUIRED_MASK4)) ||     \
+          (((bit)>>5)==5 && (1UL<<((bit)&31) & REQUIRED_MASK5)) ||     \
+          (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) ||     \
+          (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) )      \
+         ? 1 :                                                         \
+         test_bit(bit, (c)->x86_capability))
 #define boot_cpu_has(bit)      cpu_has(&boot_cpu_data, bit)
 
 #define cpu_has_fpu            boot_cpu_has(X86_FEATURE_FPU)
index 096a2a8eb1da6d8ef5df6da452a226a13f4f5798..c03290ccecb274889663681107cce207501d2cb6 100644 (file)
 
 #ifndef __ASSEMBLY__
 
+struct e820entry {
+       u64 addr;       /* start of memory segment */
+       u64 size;       /* size of memory segment */
+       u32 type;       /* type of memory segment */
+} __attribute__((packed));
+
 struct e820map {
-    int nr_map;
-    struct e820entry {
-       unsigned long long addr;        /* start of memory segment */
-       unsigned long long size;        /* size of memory segment */
-       unsigned long type;             /* type of memory segment */
-    } map[E820MAX];
+       u32 nr_map;
+       struct e820entry map[E820MAX];
 };
 
 extern struct e820map e820;
index 64b6d0baedbce7109c8691095e55b039186750c2..392d3fe5d45ecf280897f39d0af6542cbe021ec2 100644 (file)
@@ -56,48 +56,11 @@ struct pci_dev;
 #define pci_unmap_len(PTR, LEN_NAME)           (0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
 
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask)   (1)
-
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
-       return ((dma64_addr_t) page_to_phys(page) +
-               (dma64_addr_t) offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-       return pfn_to_page(dma_addr >> PAGE_SHIFT);
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-       return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-       flush_write_buffers();
-}
-
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                               enum pci_mmap_state mmap_state, int write_combine);
 
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
index 338668bfb0a2a69ae0ebb3458b94ebddf1d9ae22..94e0c147c165333b853941f547460b4efe783371 100644 (file)
@@ -119,6 +119,7 @@ void __init cpu_detect(struct cpuinfo_x86 *c);
 extern void identify_boot_cpu(void);
 extern void identify_secondary_cpu(struct cpuinfo_x86 *);
 extern void print_cpu_info(struct cpuinfo_x86 *);
+extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 extern unsigned short num_cache_leaves;
 
index 9db866c1e64c4b03bc0e7fc96509ef69e9344f0e..65848a007050911e3207b1d2e682ba4499c25ec9 100644 (file)
@@ -3,32 +3,53 @@
 
 /* Define minimum CPUID feature set for kernel These bits are checked
    really early to actually display a visible error message before the
-   kernel dies.  Only add word 0 bits here
+   kernel dies.  Make sure to assign features to the proper mask!
 
    Some requirements that are not in CPUID yet are also in the
-   CONFIG_X86_MINIMUM_CPU mode which is checked too.
+   CONFIG_X86_MINIMUM_CPU_FAMILY which is checked too.
 
    The real information is in arch/i386/Kconfig.cpu, this just converts
    the CONFIGs into a bitmask */
 
+#ifndef CONFIG_MATH_EMULATION
+# define NEED_FPU      (1<<(X86_FEATURE_FPU & 31))
+#else
+# define NEED_FPU      0
+#endif
+
 #ifdef CONFIG_X86_PAE
-#define NEED_PAE       (1<<X86_FEATURE_PAE)
+# define NEED_PAE      (1<<(X86_FEATURE_PAE & 31))
 #else
-#define NEED_PAE       0
+# define NEED_PAE      0
 #endif
 
 #ifdef CONFIG_X86_CMOV
-#define NEED_CMOV      (1<<X86_FEATURE_CMOV)
+# define NEED_CMOV     (1<<(X86_FEATURE_CMOV & 31))
 #else
-#define NEED_CMOV      0
+# define NEED_CMOV     0
 #endif
 
 #ifdef CONFIG_X86_CMPXCHG64
-#define NEED_CMPXCHG64  (1<<X86_FEATURE_CX8)
+# define NEED_CX8      (1<<(X86_FEATURE_CX8 & 31))
+#else
+# define NEED_CX8      0
+#endif
+
+#define REQUIRED_MASK0 (NEED_FPU|NEED_PAE|NEED_CMOV|NEED_CX8)
+
+#ifdef CONFIG_X86_USE_3DNOW
+# define NEED_3DNOW    (1<<(X86_FEATURE_3DNOW & 31))
 #else
-#define NEED_CMPXCHG64  0
+# define NEED_3DNOW    0
 #endif
 
-#define REQUIRED_MASK1 (NEED_PAE|NEED_CMOV|NEED_CMPXCHG64)
+#define REQUIRED_MASK1 (NEED_3DNOW)
+
+#define REQUIRED_MASK2 0
+#define REQUIRED_MASK3 0
+#define REQUIRED_MASK4 0
+#define REQUIRED_MASK5 0
+#define REQUIRED_MASK6 0
+#define REQUIRED_MASK7 0
 
 #endif
index 0e8077cbfdac7da388789be548d599c0839b8fbf..0d5bff9dc4a5e2133ef7d29bf7287e9381368ae3 100644 (file)
 #define NEW_CL_POINTER         0x228   /* Relative to real mode data */
 
 #ifndef __ASSEMBLY__
+
+#include <asm/bootparam.h>
+
 /*
  * This is set up by the setup-routine at boot-time
  */
-extern unsigned char boot_params[PARAM_SIZE];
+extern struct boot_params boot_params;
 
-#define PARAM  (boot_params)
+#define PARAM  ((char *)&boot_params)
 #define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
 #define EXT_MEM_K (*(unsigned short *) (PARAM+2))
 #define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
@@ -39,8 +42,7 @@ extern unsigned char boot_params[PARAM_SIZE];
 #define E820_MAP    ((struct e820entry *) (PARAM+E820MAP))
 #define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
 #define IST_INFO   (*(struct ist_info *) (PARAM+0x60))
-#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
-#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
+#define SYS_DESC_TABLE (*(struct sys_desc_table *)(PARAM+0xa0))
 #define EFI_SYSTAB ((efi_system_table_t *) *((unsigned long *)(PARAM+0x1c4)))
 #define EFI_MEMDESC_SIZE (*((unsigned long *) (PARAM+0x1c8)))
 #define EFI_MEMDESC_VERSION (*((unsigned long *) (PARAM+0x1cc)))
index 41098f459684c41f82cc26c6812f3b21deacb400..edd5d01028df93d8d88ad68dbdd1322261bee790 100644 (file)
@@ -48,6 +48,7 @@ enum {
        IA64_MCA_RENDEZ_CHECKIN_NOTDONE =       0x0,
        IA64_MCA_RENDEZ_CHECKIN_DONE    =       0x1,
        IA64_MCA_RENDEZ_CHECKIN_INIT    =       0x2,
+       IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA  =       0x3,
 };
 
 /* Information maintained by the MC infrastructure */
index 5a5d1c2ce39d1510e1d2a56dc1322929bab25029..0149097b736d70bd5e4d2f73801b5805ffe8a88a 100644 (file)
@@ -71,14 +71,6 @@ pcibios_penalize_isa_irq (int irq, int active)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)          \
        (((PTR)->LEN_NAME) = (VAL))
 
-/* The ia64 platform always supports 64-bit addressing. */
-#define pci_dac_dma_supported(pci_dev, mask)           (1)
-#define pci_dac_page_to_dma(dev,pg,off,dir)            ((dma_addr_t) page_to_bus(pg) + (off))
-#define pci_dac_dma_to_page(dev,dma_addr)              (virt_to_page(bus_to_virt(dma_addr)))
-#define pci_dac_dma_to_offset(dev,dma_addr)            offset_in_page(dma_addr)
-#define pci_dac_dma_sync_single_for_cpu(dev,dma_addr,len,dir)  do { } while (0)
-#define pci_dac_dma_sync_single_for_device(dev,dma_addr,len,dir)       do { mb(); } while (0)
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
@@ -104,10 +96,12 @@ extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
 #define HAVE_PCI_LEGACY
 extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
                                      struct vm_area_struct *vma);
-extern ssize_t pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off,
-                                 size_t count);
-extern ssize_t pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off,
-                                  size_t count);
+extern ssize_t pci_read_legacy_io(struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
+                                 char *buf, loff_t off, size_t count);
+extern ssize_t pci_write_legacy_io(struct kobject *kobj,
+                                  struct bin_attribute *bin_attr,
+                                  char *buf, loff_t off, size_t count);
 extern int pci_mmap_legacy_mem(struct kobject *kobj,
                               struct bin_attribute *attr,
                               struct vm_area_struct *vma);
@@ -143,10 +137,6 @@ static inline int pci_proc_domain(struct pci_bus *bus)
        return (pci_domain_nr(bus) != 0);
 }
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 extern void pcibios_resource_to_bus(struct pci_dev *dev,
                struct pci_bus_region *region, struct resource *res);
 
index d3566a298fa40b773a96d3518e1fd1f71782eec0..676b31a08c61dc8fd366d1147b8572080fca4e65 100644 (file)
@@ -32,6 +32,7 @@
 #define  SN_SAL_NO_FAULT_ZONE_VIRTUAL             0x02000010
 #define  SN_SAL_NO_FAULT_ZONE_PHYSICAL            0x02000011
 #define  SN_SAL_PRINT_ERROR                       0x02000012
+#define  SN_SAL_REGISTER_PMI_HANDLER              0x02000014
 #define  SN_SAL_SET_ERROR_HANDLING_FEATURES       0x0200001a   // reentrant
 #define  SN_SAL_GET_FIT_COMPT                     0x0200001b   // reentrant
 #define  SN_SAL_GET_SAPIC_INFO                     0x0200001d
@@ -679,6 +680,25 @@ sn_register_nofault_code(u64 start_addr, u64 end_addr, u64 return_addr,
        return ret_stuff.status;
 }
 
+/*
+ * Register or unregister a function to handle a PMI received by a CPU.
+ * Before calling the registered handler, SAL sets r1 to the value that
+ * was passed in as the global_pointer.
+ *
+ * If the handler pointer is NULL, then the currently registered handler
+ * will be unregistered.
+ *
+ * Returns 0 on success, or a negative value if an error occurred.
+ */
+static inline int
+sn_register_pmi_handler(u64 handler, u64 global_pointer)
+{
+       struct ia64_sal_retval ret_stuff;
+       ia64_sal_oemcall(&ret_stuff, SN_SAL_REGISTER_PMI_HANDLER, handler,
+                        global_pointer, 0, 0, 0, 0, 0);
+       return ret_stuff.status;
+}
+
 /*
  * Change or query the coherence domain for this partition. Each cpu-based
  * nasid is represented by a bit in an array of 64-bit words:
index 9d2c07abe44f90d0657f27894c2fff844b9eeb57..678cb0b52314dac16a1cfb9fc9dbd44b5eeeed16 100644 (file)
@@ -54,8 +54,4 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
  */
 #define PCI_DMA_BUS_IS_PHYS    (1)
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* _ASM_M68K_PCI_H */
index e04c77e1184da3bb8dcce624e70db0fc4281fed8..a13f3cc87451be8f5fe1dd46bd8776afd9b5fd08 100644 (file)
@@ -24,16 +24,6 @@ static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
        return 1;
 }
 
-/*
- * Not supporting more than 32-bit PCI bus addresses now, but
- * must satisfy references to this function.  Change if needed.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* CONFIG_COMEMPCI */
 
 #endif /* M68KNOMMU_PCI_H */
index 432653d7ae09326dafde8ef0b23504ca27b69300..67c3f8ec0303bba4e95fdf1eb00b9638d51d62ac 100644 (file)
@@ -132,7 +132,8 @@ typedef u32         compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
-       return (void __user *)(long)uptr;
+       /* cast to a __user pointer via "unsigned long" makes sparse happy */
+       return (void __user *)(unsigned long)(long)uptr;
 }
 
 static inline compat_uptr_t ptr_to_compat(void __user *uptr)
index 12bcc1f9fba97387102382cae58f676a728125d2..7ba92890ea13eeeef95f55d9bb0e9b9429ed593b 100644 (file)
@@ -212,7 +212,8 @@ static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
                 */
                if (__IS_LOW512(phys_addr) && __IS_LOW512(last_addr) &&
                    flags == _CACHE_UNCACHED)
-                       return (void __iomem *)CKSEG1ADDR(phys_addr);
+                       return (void __iomem *)
+                               (unsigned long)CKSEG1ADDR(phys_addr);
        }
 
        return __ioremap(offset, size, flags);
index 3ca6a076124d745c163aaf918872507a7b4bccfd..97102ebc54b19d44137945dcac23833eceec6ada 100644 (file)
@@ -24,7 +24,7 @@ static inline int irq_canonicalize(int irq)
 #define irq_canonicalize(irq) (irq)    /* Sane hardware, sane code ... */
 #endif
 
-#ifdef CONFIG_MIPS_MT_SMTC
+#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
 /*
  * Clear interrupt mask handling "backstop" if irq_hwmask
  * entry so indicates. This implies that the ack() or end()
index 88cf546719b8f74ddec13ba9754176e7d14291fa..1e7beae7222980f2865d2b00f13dbfa3574e2f00 100644 (file)
@@ -36,7 +36,8 @@ static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
 
 static inline int plat_iounmap(const volatile void __iomem *addr)
 {
-       return (unsigned long)addr >= (unsigned long)(int)TXX9_DIRECTMAP_BASE;
+       return (unsigned long)addr >=
+               (unsigned long)(int)(TXX9_DIRECTMAP_BASE & 0xffffffff);
 }
 
 #endif /* __ASM_MACH_TX49XX_IOREMAP_H */
index 706b3691f57e25cb0477923b976b15574b6ec409..18f47f1e8cd53eb14a44319a80ffe694b9b6b385 100644 (file)
@@ -707,10 +707,10 @@ do {                                                                      \
  */
 #define __read_64bit_c0_split(source, sel)                             \
 ({                                                                     \
-       unsigned long long val;                                         \
-       unsigned long flags;                                            \
+       unsigned long long __val;                                       \
+       unsigned long __flags;                                          \
                                                                        \
-       local_irq_save(flags);                                          \
+       local_irq_save(__flags);                                        \
        if (sel == 0)                                                   \
                __asm__ __volatile__(                                   \
                        ".set\tmips64\n\t"                              \
@@ -719,7 +719,7 @@ do {                                                                        \
                        "dsrl\t%M0, %M0, 32\n\t"                        \
                        "dsrl\t%L0, %L0, 32\n\t"                        \
                        ".set\tmips0"                                   \
-                       : "=r" (val));                                  \
+                       : "=r" (__val));                                \
        else                                                            \
                __asm__ __volatile__(                                   \
                        ".set\tmips64\n\t"                              \
@@ -728,17 +728,17 @@ do {                                                                      \
                        "dsrl\t%M0, %M0, 32\n\t"                        \
                        "dsrl\t%L0, %L0, 32\n\t"                        \
                        ".set\tmips0"                                   \
-                       : "=r" (val));                                  \
-       local_irq_restore(flags);                                       \
+                       : "=r" (__val));                                \
+       local_irq_restore(__flags);                                     \
                                                                        \
-       val;                                                            \
+       __val;                                                          \
 })
 
 #define __write_64bit_c0_split(source, sel, val)                       \
 do {                                                                   \
-       unsigned long flags;                                            \
+       unsigned long __flags;                                          \
                                                                        \
-       local_irq_save(flags);                                          \
+       local_irq_save(__flags);                                        \
        if (sel == 0)                                                   \
                __asm__ __volatile__(                                   \
                        ".set\tmips64\n\t"                              \
@@ -759,7 +759,7 @@ do {                                                                        \
                        "dmtc0\t%L0, " #source ", " #sel "\n\t"         \
                        ".set\tmips0"                                   \
                        : : "r" (val));                                 \
-       local_irq_restore(flags);                                       \
+       local_irq_restore(__flags);                                     \
 } while (0)
 
 #define read_c0_index()                __read_32bit_c0_register($0, 0)
index a59d54749eef0b2ebc581e35df61cc7d5b997de3..4fcc185cb2d1f65a7a2267f851d5d6ec97f2306b 100644 (file)
@@ -121,20 +121,6 @@ extern unsigned int PCI_DMA_BUS_IS_PHYS;
 
 #endif /* CONFIG_DMA_NEED_PCI_MAP_STATE  */
 
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask)   (1)
-
-extern dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-       struct page *page, unsigned long offset, int direction);
-extern struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-       dma64_addr_t dma_addr);
-extern unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-       dma64_addr_t dma_addr);
-extern void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-       dma64_addr_t dma_addr, size_t len, int direction);
-extern void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-       dma64_addr_t dma_addr, size_t len, int direction);
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
@@ -181,10 +167,6 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 /* implement the pci_ DMA API in terms of the generic device dma_ one */
 #include <asm-generic/pci-dma-compat.h>
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 /* Do platform specific device initialization at pci_enable_device() time */
 extern int pcibios_plat_dev_init(struct pci_dev *dev);
 
diff --git a/include/asm-mips/rtc.h b/include/asm-mips/rtc.h
deleted file mode 100644 (file)
index 82ad401..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * include/asm-mips/rtc.h
- *
- * (Really an interface for drivers/char/genrtc.c)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * Please read the COPYING file for all license details.
- */
-
-#ifndef _MIPS_RTC_H
-#define _MIPS_RTC_H
-
-#ifdef __KERNEL__
-
-#include <linux/rtc.h>
-#include <asm/time.h>
-
-#define RTC_PIE 0x40            /* periodic interrupt enable */
-#define RTC_AIE 0x20            /* alarm interrupt enable */
-#define RTC_UIE 0x10            /* update-finished interrupt enable */
-
-/* some dummy definitions */
-#define RTC_BATT_BAD 0x100      /* battery bad */
-#define RTC_SQWE 0x08           /* enable square-wave output */
-#define RTC_DM_BINARY 0x04      /* all time/date values are BCD if clear */
-#define RTC_24H 0x02            /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01         /* auto switch DST - works f. USA only */
-
-static inline unsigned int get_rtc_time(struct rtc_time *time)
-{
-       unsigned long nowtime;
-
-       nowtime = rtc_mips_get_time();
-       to_tm(nowtime, time);
-       time->tm_year -= 1900;
-
-       return RTC_24H;
-}
-
-static inline int set_rtc_time(struct rtc_time *time)
-{
-       unsigned long nowtime;
-       int ret;
-
-       nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
-                       time->tm_mday, time->tm_hour, time->tm_min,
-                       time->tm_sec);
-       ret = rtc_mips_set_time(nowtime);
-
-       return ret;
-}
-
-static inline unsigned int get_rtc_ss(void)
-{
-       struct rtc_time h;
-
-       get_rtc_time(&h);
-       return h.tm_sec;
-}
-
-static inline int get_rtc_pll(struct rtc_pll_info *pll)
-{
-       return -EINVAL;
-}
-
-static inline int set_rtc_pll(struct rtc_pll_info *pll)
-{
-       return -EINVAL;
-}
-#endif
-#endif
index fff7a73e22d0f666387097a336bbd6ef1cb26bae..bb8f5c29c3d9f9a5e0c72c4497993fec46fcfae2 100644 (file)
 /*
  * TLB debugging functions:
  */
-extern void dump_tlb(int first, int last);
 extern void dump_tlb_all(void);
-extern void dump_tlb_wired(void);
-extern void dump_tlb_addr(unsigned long addr);
-extern void dump_tlb_nonwired(void);
 
 #endif /* __ASM_TLBDEBUG_H */
index 8109cda557dce747e0d0032c8bd59eda4b48f046..0bcdd3a5c2560b6817174af92d1e1dbfe2a9cd07 100644 (file)
 #ifndef __NEC_VR41XX_GIU_H
 #define __NEC_VR41XX_GIU_H
 
+/*
+ * NEC VR4100 series GIU platform device IDs.
+ */
+enum {
+       GPIO_50PINS_PULLUPDOWN,
+       GPIO_36PINS,
+       GPIO_48PINS_EDGE_SELECT,
+};
+
 typedef enum {
        IRQ_TRIGGER_LEVEL,
        IRQ_TRIGGER_EDGE,
index 1fcf6e8082b42621271bc87aa344e4ba4501ce5c..98cdb409648513dddaa702ef168bba48513e9c91 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef __NEC_VR41XX_SIU_H
 #define __NEC_VR41XX_SIU_H
 
+#define SIU_PORTS_MAX 2
+
 typedef enum {
        SIU_INTERFACE_RS232C,
        SIU_INTERFACE_IRDA,
index 7b3be9ac0dda3f67032f95ac5c4f8493bf6f1895..61fbd57a83232ae5d9d7b100d0341aeb22651986 100644 (file)
@@ -238,9 +238,6 @@ extern inline void pcibios_register_hba(struct pci_hba_data *x)
 #define PCIBIOS_MIN_IO          0x10
 #define PCIBIOS_MIN_MEM         0x1000 /* NBPG - but pci/setup-res.c dies */
 
-/* Don't support DAC yet. */
-#define pci_dac_dma_supported(pci_dev, mask)   (0)
-
 /* export the pci_ DMA API in terms of the dma_ one */
 #include <asm-generic/pci-dma-compat.h>
 
@@ -284,10 +281,6 @@ pcibios_select_root(struct pci_dev *pdev, struct resource *res)
        return root;
 }
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 static inline void pcibios_penalize_isa_irq(int irq, int active)
 {
        /* We don't need to penalize isa irq's */
index a19a6f1a1cf10dd54fcce72e94e9e19e135db966..f6bd804d9090e3d714393c284957e428f7a43567 100644 (file)
@@ -61,7 +61,6 @@ struct dma_mapping_ops {
        void            (*unmap_sg)(struct device *dev, struct scatterlist *sg,
                                int nents, enum dma_data_direction direction);
        int             (*dma_supported)(struct device *dev, u64 mask);
-       int             (*dac_dma_supported)(struct device *dev, u64 mask);
        int             (*set_dma_mask)(struct device *dev, u64 dma_mask);
 };
 
index ce0f13e8eb141d6bc65aedd9aadd92a204d8c577..e16e7bc9ab5cf2640364ea19586319edbc080025 100644 (file)
@@ -74,18 +74,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 extern void set_pci_dma_ops(struct dma_mapping_ops *dma_ops);
 extern struct dma_mapping_ops *get_pci_dma_ops(void);
 
-/* For DAC DMA, we currently don't support it by default, but
- * we let 64-bit platforms override this.
- */
-static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask)
-{
-       struct dma_mapping_ops *d = get_pci_dma_ops();
-
-       if (d && d->dac_dma_supported)
-               return d->dac_dma_supported(&hwdev->dev, mask);
-       return 0;
-}
-
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
                                        unsigned long *strategy_parameter)
@@ -124,12 +112,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 }
 #endif
 
-/*
- * At present there are very few 32-bit PPC machines that can have
- * memory above the 4GB point, and we don't support that.
- */
-#define pci_dac_dma_supported(pci_dev, mask)   (0)
-
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
 
@@ -243,8 +225,6 @@ extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
 
 extern int pci_read_irq_line(struct pci_dev *dev);
 
-extern void pcibios_add_platform_entries(struct pci_dev *dev);
-
 struct file;
 extern pgprot_t        pci_phys_mem_access_prot(struct file *file,
                                         unsigned long pfn,
index 9d162028dab92809d4d6b49bc9fce254ccc3932b..d2442cd72a5961ac923a0ac789d3d321808b3fc7 100644 (file)
@@ -102,12 +102,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 }
 #endif
 
-/*
- * At present there are very few 32-bit PPC machines that can have
- * memory above the 4GB point, and we don't support that.
- */
-#define pci_dac_dma_supported(pci_dev, mask)   (0)
-
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
 
@@ -145,8 +139,6 @@ pcibios_select_root(struct pci_dev *pdev, struct resource *res)
        return root;
 }
 
-extern void pcibios_add_platform_entries(struct pci_dev *dev);
-
 struct file;
 extern pgprot_t        pci_phys_mem_access_prot(struct file *file,
                                         unsigned long pfn,
index b1f9a9e0231e000df1ccf1a40a1a9d3b60427453..2757ce096ff73878f717ca2373daa8bc7938006d 100644 (file)
@@ -110,11 +110,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
 #endif
 
-/* Not supporting more than 32-bit PCI bus addresses now, but
- * must satisfy references to this function.  Change if needed.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
@@ -134,10 +129,6 @@ int pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
 int pciauto_assign_resources(int busno, struct pci_channel *hose);
 #endif
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
 
 /* generic pci stuff */
index aa8043089bb695133f19992d87deed7576c4f2db..57a67cf7a5c4e06309e25c2e70569dadb921fd23 100644 (file)
@@ -72,11 +72,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
 #endif
 
-/* Not supporting more than 32-bit PCI bus addresses now, but
- * must satisfy references to this function.  Change if needed.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
 /* These macros should be used after a pci_map_sg call has been done
  * to get bus addresses of each of the SG entries and their lengths.
  * You should only work with the number of sg entries pci_map_sg
@@ -104,10 +99,6 @@ extern void pcibios_fixup_irqs(void);
 extern int pciauto_assign_resources(int busno, struct pci_channel *hose);
 #endif
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
 
 /* generic pci stuff */
index a750c688408bb418d702153619380a9d5100d8d6..b93b6c79e08f6d48692f1539ced9fb7dbfeb8629 100644 (file)
@@ -142,8 +142,6 @@ static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
        return 1;
 }
 
-#define pci_dac_dma_supported(dev, mask)       (0)
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
@@ -154,10 +152,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 }
 #endif
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #define PCI_DMA_ERROR_CODE      (~(dma_addr_t)0x0)
 
 static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
index 47cea16e1badd54d867d2add632aa6fdaa96c6e0..e11ac100f043469664c2870b90b3a1731de37e17 100644 (file)
@@ -206,49 +206,6 @@ extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
 #define PCI64_REQUIRED_MASK    (~(dma64_addr_t)0)
 #define PCI64_ADDR_BASE                0xfffc000000000000UL
 
-/* Usage of the pci_dac_foo interfaces is only valid if this
- * test passes.
- */
-#define pci_dac_dma_supported(pci_dev, mask) \
-       ((((mask) & PCI64_REQUIRED_MASK) == PCI64_REQUIRED_MASK) ? 1 : 0)
-
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
-       return (PCI64_ADDR_BASE +
-               __pa(page_address(page)) + offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-       unsigned long paddr = (dma_addr & PAGE_MASK) - PCI64_ADDR_BASE;
-
-       return virt_to_page(__va(paddr));
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-       return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-       /* DAC cycle addressing does not make use of the
-        * PCI controller's streaming cache, so nothing to do.
-        */
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-       /* DAC cycle addressing does not make use of the
-        * PCI controller's streaming cache, so nothing to do.
-        */
-}
-
 #define PCI_DMA_ERROR_CODE     (~(dma_addr_t)0x0)
 
 static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
@@ -303,10 +260,6 @@ pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 
 extern struct resource *pcibios_select_root(struct pci_dev *, struct resource *);
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
        return PCI_IRQ_NONE;
index 4581826e1cac9dcf170edba22a36d8d143ead3e8..de2a7d0a81cc1d7345b1adc9b37eeb4656023d93 100644 (file)
@@ -116,8 +116,4 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
 extern void pci_iounmap (struct pci_dev *dev, void __iomem *addr);
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __V850_PCI_H__ */
index 9f7f02cb039127e4045a5dc5fe4d278daa24ed61..e85d261b79bf0ee140ab1f5f349b6b25e100d25d 100644 (file)
@@ -64,7 +64,6 @@
 /* As we don't really support PCI DMA to cpu memory, and use bounce-buffers
    instead, perversely enough, this becomes always true! */
 # define pci_dma_supported(dev, mask)          1
-# define pci_dac_dma_supported(dev, mask)      0
 # define pcibios_assign_all_busses()           1
 
 #endif /* CONFIG_RTE_MB_A_PCI */
index a094276407647ecbfea524af86ef686133be4f91..eea7aecfac787cef93d9ae09b66745cb313dda06 100644 (file)
@@ -5,6 +5,41 @@
 
 #include <linux/types.h>
 #include <linux/stddef.h>
+
+/*
+ * Alternative inline assembly for SMP.
+ *
+ * The LOCK_PREFIX macro defined here replaces the LOCK and
+ * LOCK_PREFIX macros used everywhere in the source tree.
+ *
+ * SMP alternatives use the same data structures as the other
+ * alternatives and the X86_FEATURE_UP flag to indicate the case of a
+ * UP system running a SMP kernel.  The existing apply_alternatives()
+ * works fine for patching a SMP kernel for UP.
+ *
+ * The SMP alternative tables can be kept after boot and contain both
+ * UP and SMP versions of the instructions to allow switching back to
+ * SMP at runtime, when hotplugging in a new CPU, which is especially
+ * useful in virtualized environments.
+ *
+ * The very common lock prefix is handled as special case in a
+ * separate table which is a pure address list without replacement ptr
+ * and size information.  That keeps the table sizes small.
+ */
+
+#ifdef CONFIG_SMP
+#define LOCK_PREFIX \
+               ".section .smp_locks,\"a\"\n"   \
+               "  .align 8\n"                  \
+               "  .quad 661f\n" /* address */  \
+               ".previous\n"                   \
+               "661:\n\tlock; "
+
+#else /* ! CONFIG_SMP */
+#define LOCK_PREFIX ""
+#endif
+
+/* This must be included *after* the definition of LOCK_PREFIX */
 #include <asm/cpufeature.h>
 
 struct alt_instr {
@@ -108,39 +143,6 @@ static inline void alternatives_smp_switch(int smp) {}
  */
 #define ASM_OUTPUT2(a, b) a, b
 
-/*
- * Alternative inline assembly for SMP.
- *
- * The LOCK_PREFIX macro defined here replaces the LOCK and
- * LOCK_PREFIX macros used everywhere in the source tree.
- *
- * SMP alternatives use the same data structures as the other
- * alternatives and the X86_FEATURE_UP flag to indicate the case of a
- * UP system running a SMP kernel.  The existing apply_alternatives()
- * works fine for patching a SMP kernel for UP.
- *
- * The SMP alternative tables can be kept after boot and contain both
- * UP and SMP versions of the instructions to allow switching back to
- * SMP at runtime, when hotplugging in a new CPU, which is especially
- * useful in virtualized environments.
- *
- * The very common lock prefix is handled as special case in a
- * separate table which is a pure address list without replacement ptr
- * and size information.  That keeps the table sizes small.
- */
-
-#ifdef CONFIG_SMP
-#define LOCK_PREFIX \
-               ".section .smp_locks,\"a\"\n"   \
-               "  .align 8\n"                  \
-               "  .quad 661f\n" /* address */  \
-               ".previous\n"                   \
-               "661:\n\tlock; "
-
-#else /* ! CONFIG_SMP */
-#define LOCK_PREFIX ""
-#endif
-
 struct paravirt_patch;
 #ifdef CONFIG_PARAVIRT
 void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end);
index 96b228e6e79cd1c086df76d6c00f7646a06b98f9..3c46cea8db7faabfce09b6aa0dca38f48208ea3e 100644 (file)
@@ -1,15 +1 @@
-#ifndef _LINUX_BOOT_H
-#define _LINUX_BOOT_H
-
-/* Don't touch these, unless you really know what you're doing. */
-#define DEF_INITSEG    0x9000
-#define DEF_SYSSEG     0x1000
-#define DEF_SETUPSEG   0x9020
-#define DEF_SYSSIZE    0x7F00
-
-/* Internal svga startup constants */
-#define NORMAL_VGA     0xffff          /* 80x25 mode */
-#define EXTENDED_VGA   0xfffe          /* 80x50 mode */
-#define ASK_VGA                0xfffd          /* ask for it at bootup */
-
-#endif
+#include <asm-i386/boot.h>
diff --git a/include/asm-x86_64/bootparam.h b/include/asm-x86_64/bootparam.h
new file mode 100644 (file)
index 0000000..aa82e52
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-i386/bootparam.h>
index 0b3c686139f1505340db96be8dc52585f584a9fc..8baefc3beb2e1e7682c6000e7875c96db88c1fd5 100644 (file)
 #ifndef __ASM_X8664_CPUFEATURE_H
 #define __ASM_X8664_CPUFEATURE_H
 
-#define NCAPINTS       7       /* N 32-bit words worth of info */
+#include <asm-i386/cpufeature.h>
 
-/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
-#define X86_FEATURE_FPU                (0*32+ 0) /* Onboard FPU */
-#define X86_FEATURE_VME                (0*32+ 1) /* Virtual Mode Extensions */
-#define X86_FEATURE_DE         (0*32+ 2) /* Debugging Extensions */
-#define X86_FEATURE_PSE        (0*32+ 3) /* Page Size Extensions */
-#define X86_FEATURE_TSC                (0*32+ 4) /* Time Stamp Counter */
-#define X86_FEATURE_MSR                (0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */
-#define X86_FEATURE_PAE                (0*32+ 6) /* Physical Address Extensions */
-#define X86_FEATURE_MCE                (0*32+ 7) /* Machine Check Architecture */
-#define X86_FEATURE_CX8                (0*32+ 8) /* CMPXCHG8 instruction */
-#define X86_FEATURE_APIC       (0*32+ 9) /* Onboard APIC */
-#define X86_FEATURE_SEP                (0*32+11) /* SYSENTER/SYSEXIT */
-#define X86_FEATURE_MTRR       (0*32+12) /* Memory Type Range Registers */
-#define X86_FEATURE_PGE                (0*32+13) /* Page Global Enable */
-#define X86_FEATURE_MCA                (0*32+14) /* Machine Check Architecture */
-#define X86_FEATURE_CMOV       (0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
-#define X86_FEATURE_PAT                (0*32+16) /* Page Attribute Table */
-#define X86_FEATURE_PSE36      (0*32+17) /* 36-bit PSEs */
-#define X86_FEATURE_PN         (0*32+18) /* Processor serial number */
-#define X86_FEATURE_CLFLSH     (0*32+19) /* Supports the CLFLUSH instruction */
-#define X86_FEATURE_DS         (0*32+21) /* Debug Store */
-#define X86_FEATURE_ACPI       (0*32+22) /* ACPI via MSR */
-#define X86_FEATURE_MMX                (0*32+23) /* Multimedia Extensions */
-#define X86_FEATURE_FXSR       (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */
-                                         /* of FPU context), and CR4.OSFXSR available */
-#define X86_FEATURE_XMM                (0*32+25) /* Streaming SIMD Extensions */
-#define X86_FEATURE_XMM2       (0*32+26) /* Streaming SIMD Extensions-2 */
-#define X86_FEATURE_SELFSNOOP  (0*32+27) /* CPU self snoop */
-#define X86_FEATURE_HT         (0*32+28) /* Hyper-Threading */
-#define X86_FEATURE_ACC                (0*32+29) /* Automatic clock control */
-#define X86_FEATURE_IA64       (0*32+30) /* IA-64 processor */
-
-/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
-/* Don't duplicate feature flags which are redundant with Intel! */
-#define X86_FEATURE_SYSCALL    (1*32+11) /* SYSCALL/SYSRET */
-#define X86_FEATURE_MMXEXT     (1*32+22) /* AMD MMX extensions */
-#define X86_FEATURE_FXSR_OPT   (1*32+25) /* FXSR optimizations */
-#define X86_FEATURE_RDTSCP     (1*32+27) /* RDTSCP */
-#define X86_FEATURE_LM         (1*32+29) /* Long Mode (x86-64) */
-#define X86_FEATURE_3DNOWEXT   (1*32+30) /* AMD 3DNow! extensions */
-#define X86_FEATURE_3DNOW      (1*32+31) /* 3DNow! */
-
-/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
-#define X86_FEATURE_RECOVERY   (2*32+ 0) /* CPU in recovery mode */
-#define X86_FEATURE_LONGRUN    (2*32+ 1) /* Longrun power control */
-#define X86_FEATURE_LRTI       (2*32+ 3) /* LongRun table interface */
-
-/* Other features, Linux-defined mapping, word 3 */
-/* This range is used for feature bits which conflict or are synthesized */
-#define X86_FEATURE_CXMMX      (3*32+ 0) /* Cyrix MMX extensions */
-#define X86_FEATURE_K6_MTRR    (3*32+ 1) /* AMD K6 nonstandard MTRRs */
-#define X86_FEATURE_CYRIX_ARR  (3*32+ 2) /* Cyrix ARRs (= MTRRs) */
-#define X86_FEATURE_CENTAUR_MCR        (3*32+ 3) /* Centaur MCRs (= MTRRs) */
-#define X86_FEATURE_REP_GOOD   (3*32+ 4) /* rep microcode works well on this CPU */
-#define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
-#define X86_FEATURE_SYNC_RDTSC  (3*32+6)  /* RDTSC syncs CPU core */
-#define X86_FEATURE_FXSAVE_LEAK (3*32+7)  /* FIP/FOP/FDP leaks through FXSAVE */
-#define X86_FEATURE_UP         (3*32+8) /* SMP kernel running on UP */
-#define X86_FEATURE_ARCH_PERFMON (3*32+9) /* Intel Architectural PerfMon */
-#define X86_FEATURE_PEBS       (3*32+10) /* Precise-Event Based Sampling */
-#define X86_FEATURE_BTS                (3*32+11) /* Branch Trace Store */
-
-/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
-#define X86_FEATURE_XMM3       (4*32+ 0) /* Streaming SIMD Extensions-3 */
-#define X86_FEATURE_MWAIT      (4*32+ 3) /* Monitor/Mwait support */
-#define X86_FEATURE_DSCPL      (4*32+ 4) /* CPL Qualified Debug Store */
-#define X86_FEATURE_EST                (4*32+ 7) /* Enhanced SpeedStep */
-#define X86_FEATURE_TM2                (4*32+ 8) /* Thermal Monitor 2 */
-#define X86_FEATURE_CID                (4*32+10) /* Context ID */
-#define X86_FEATURE_CX16       (4*32+13) /* CMPXCHG16B */
-#define X86_FEATURE_XTPR       (4*32+14) /* Send Task Priority Messages */
-
-/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
-#define X86_FEATURE_XSTORE     (5*32+ 2) /* on-CPU RNG present (xstore insn) */
-#define X86_FEATURE_XSTORE_EN  (5*32+ 3) /* on-CPU RNG enabled */
-#define X86_FEATURE_XCRYPT     (5*32+ 6) /* on-CPU crypto (xcrypt insn) */
-#define X86_FEATURE_XCRYPT_EN  (5*32+ 7) /* on-CPU crypto enabled */
-
-/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
-#define X86_FEATURE_LAHF_LM    (6*32+ 0) /* LAHF/SAHF in long mode */
-#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */
-
-#define cpu_has(c, bit)                test_bit(bit, (c)->x86_capability)
-#define boot_cpu_has(bit)      test_bit(bit, boot_cpu_data.x86_capability)
-
-#define cpu_has_fpu            1
+#undef  cpu_has_vme
 #define cpu_has_vme            0
-#define cpu_has_de             1
-#define cpu_has_pse            1
-#define cpu_has_tsc            1
+
+#undef  cpu_has_pae
 #define cpu_has_pae            ___BUG___
-#define cpu_has_pge            1
-#define cpu_has_apic           boot_cpu_has(X86_FEATURE_APIC)
-#define cpu_has_mtrr           1
-#define cpu_has_mmx            1
-#define cpu_has_fxsr           1
-#define cpu_has_xmm            1
-#define cpu_has_xmm2           1
-#define cpu_has_xmm3           boot_cpu_has(X86_FEATURE_XMM3)
-#define cpu_has_ht             boot_cpu_has(X86_FEATURE_HT)
+
+#undef  cpu_has_mp
 #define cpu_has_mp             1 /* XXX */
+
+#undef  cpu_has_k6_mtrr
 #define cpu_has_k6_mtrr        0
+
+#undef  cpu_has_cyrix_arr
 #define cpu_has_cyrix_arr      0
+
+#undef  cpu_has_centaur_mcr
 #define cpu_has_centaur_mcr    0
-#define cpu_has_clflush               boot_cpu_has(X86_FEATURE_CLFLSH)
-#define cpu_has_ds            boot_cpu_has(X86_FEATURE_DS)
-#define cpu_has_pebs          boot_cpu_has(X86_FEATURE_PEBS)
-#define cpu_has_bts           boot_cpu_has(X86_FEATURE_BTS)
 
 #endif /* __ASM_X8664_CPUFEATURE_H */
index 6216fa3f28026b943dedaccb717c8e7edb871edb..3486e701bd8656f5e5a782cf60b892e656509756 100644 (file)
@@ -11,8 +11,6 @@
 #ifndef __E820_HEADER
 #define __E820_HEADER
 
-#include <linux/mmzone.h>
-
 #define E820MAP        0x2d0           /* our map */
 #define E820MAX        128             /* number of entries in E820MAP */
 #define E820NR 0x1e8           /* # entries in E820MAP */
@@ -30,7 +28,7 @@ struct e820entry {
 } __attribute__((packed));
 
 struct e820map {
-    int nr_map;
+       u32 nr_map;
        struct e820entry map[E820MAX];
 };
 
index 49c5e9280598729000a42e07483fa5f21da2b538..bda94fd5176f43a70c431f0079aeb6715d30a78e 100644 (file)
@@ -54,14 +54,6 @@ extern int iommu_setup(char *opt);
 
 #if defined(CONFIG_IOMMU) || defined(CONFIG_CALGARY_IOMMU)
 
-/*
- * x86-64 always supports DAC, but sometimes it is useful to force
- * devices through the IOMMU to get automatic sg list merging.
- * Optional right now.
- */
-extern int iommu_sac_force;
-#define pci_dac_dma_supported(pci_dev, mask)   (!iommu_sac_force)
-
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)      \
        dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)                \
@@ -78,8 +70,6 @@ extern int iommu_sac_force;
 #else
 /* No IOMMU */
 
-#define pci_dac_dma_supported(pci_dev, mask)    1
-
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
 #define pci_unmap_addr(PTR, ADDR_NAME)         (0)
@@ -91,36 +81,6 @@ extern int iommu_sac_force;
 
 #include <asm-generic/pci-dma-compat.h>
 
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
-       return ((dma64_addr_t) page_to_phys(page) +
-               (dma64_addr_t) offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-       return virt_to_page(__va(dma_addr));    
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-       return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-       flush_write_buffers();
-}
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
@@ -135,10 +95,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                               enum pci_mmap_state mmap_state, int write_combine);
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
 
 /* generic pci stuff */
index 461ffe4c1fccca877ac338fdf12489b1b24feada..efc87a5aff7f0f5febf0ff04f87b8f72c4a72c6f 100644 (file)
@@ -100,6 +100,7 @@ extern char ignore_irq13;
 
 extern void identify_cpu(struct cpuinfo_x86 *);
 extern void print_cpu_info(struct cpuinfo_x86 *);
+extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 extern unsigned short num_cache_leaves;
 
@@ -368,8 +369,6 @@ static inline void sync_core(void)
        asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
 } 
 
-#define cpu_has_fpu 1
-
 #define ARCH_HAS_PREFETCH
 static inline void prefetch(void *x) 
 { 
diff --git a/include/asm-x86_64/required-features.h b/include/asm-x86_64/required-features.h
new file mode 100644 (file)
index 0000000..e80d576
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _ASM_REQUIRED_FEATURES_H
+#define _ASM_REQUIRED_FEATURES_H 1
+
+/* Define minimum CPUID feature set for kernel These bits are checked
+   really early to actually display a visible error message before the
+   kernel dies.  Make sure to assign features to the proper mask!
+
+   The real information is in arch/x86_64/Kconfig.cpu, this just converts
+   the CONFIGs into a bitmask */
+
+/* x86-64 baseline features */
+#define NEED_FPU       (1<<(X86_FEATURE_FPU & 31))
+#define NEED_PSE       (1<<(X86_FEATURE_PSE & 31))
+#define NEED_MSR       (1<<(X86_FEATURE_MSR & 31))
+#define NEED_PAE       (1<<(X86_FEATURE_PAE & 31))
+#define NEED_CX8       (1<<(X86_FEATURE_CX8 & 31))
+#define NEED_PGE       (1<<(X86_FEATURE_PGE & 31))
+#define NEED_FXSR      (1<<(X86_FEATURE_FXSR & 31))
+#define NEED_CMOV      (1<<(X86_FEATURE_CMOV & 31))
+#define NEED_XMM       (1<<(X86_FEATURE_XMM & 31))
+#define NEED_XMM2      (1<<(X86_FEATURE_XMM2 & 31))
+
+#define REQUIRED_MASK0 (NEED_FPU|NEED_PSE|NEED_MSR|NEED_PAE|\
+                        NEED_CX8|NEED_PGE|NEED_FXSR|NEED_CMOV|\
+                        NEED_XMM|NEED_XMM2)
+#define SSE_MASK       (NEED_XMM|NEED_XMM2)
+
+/* x86-64 baseline features */
+#define NEED_LM                (1<<(X86_FEATURE_LM & 31))
+
+#ifdef CONFIG_X86_USE_3DNOW
+# define NEED_3DNOW    (1<<(X86_FEATURE_3DNOW & 31))
+#else
+# define NEED_3DNOW    0
+#endif
+
+#define REQUIRED_MASK1 (NEED_LM|NEED_3DNOW)
+
+#define REQUIRED_MASK2 0
+#define REQUIRED_MASK3 0
+#define REQUIRED_MASK4 0
+#define REQUIRED_MASK5 0
+#define REQUIRED_MASK6 0
+#define REQUIRED_MASK7 0
+
+#endif
index adf2bf1e187c341524e69bf7ddc7b8b2b449b9de..04b8ab21328faed255f2cfca4d02f267c9fd5fb3 100644 (file)
@@ -3,6 +3,14 @@
 
 #include <asm/cache.h>
 
+/* Simple and small GDT entries for booting only */
+
+#define GDT_ENTRY_BOOT_CS              2
+#define __BOOT_CS      (GDT_ENTRY_BOOT_CS * 8)
+
+#define GDT_ENTRY_BOOT_DS              (GDT_ENTRY_BOOT_CS + 1)
+#define __BOOT_DS      (GDT_ENTRY_BOOT_DS * 8)
+
 #define __KERNEL_CS    0x10
 #define __KERNEL_DS    0x18
 
index 24eb7fc25da830c8fc4f74ac1b0c11efe1a677b8..66410acf18b439b239fddfd195d38610f2826ebd 100644 (file)
@@ -64,9 +64,6 @@ struct pci_dev;
 #define pci_ubnmap_len(PTR, LEN_NAME)          (0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
 
-/* We cannot access memory above 4GB */
-#define pci_dac_dma_supported(pci_dev, mask)   (0)
-
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
                         enum pci_mmap_state mmap_state, int write_combine);
@@ -74,10 +71,6 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
 /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
 #define HAVE_PCI_MMAP  1
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
 
 /* Implement the pci_ DMA API in terms of the generic device dma_ one */
index 402e178b38ebd3dcc999c15b9d90b9c52769de32..509656286e5326e3f10617bea575ad56f5128602 100644 (file)
@@ -13,11 +13,13 @@ extern int pci_enable_pcie_error_reporting(struct pci_dev *dev);
 extern int pci_find_aer_capability(struct pci_dev *dev);
 extern int pci_disable_pcie_error_reporting(struct pci_dev *dev);
 extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+extern int pci_cleanup_aer_correct_error_status(struct pci_dev *dev);
 #else
-#define pci_enable_pcie_error_reporting(dev)           do { } while (0)
-#define pci_find_aer_capability(dev)                   do { } while (0)
-#define pci_disable_pcie_error_reporting(dev)          do { } while (0)
-#define pci_cleanup_aer_uncorrect_error_status(dev)    do { } while (0)
+#define pci_enable_pcie_error_reporting(dev)           (-EINVAL)
+#define pci_find_aer_capability(dev)                   (0)
+#define pci_disable_pcie_error_reporting(dev)          (-EINVAL)
+#define pci_cleanup_aer_uncorrect_error_status(dev)    (-EINVAL)
+#define pci_cleanup_aer_correct_error_status(dev)      (-EINVAL)
 #endif
 
 #endif //_AER_H_
diff --git a/include/linux/async_tx.h b/include/linux/async_tx.h
new file mode 100644 (file)
index 0000000..ff12550
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright Â© 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef _ASYNC_TX_H_
+#define _ASYNC_TX_H_
+#include <linux/dmaengine.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+/**
+ * dma_chan_ref - object used to manage dma channels received from the
+ *   dmaengine core.
+ * @chan - the channel being tracked
+ * @node - node for the channel to be placed on async_tx_master_list
+ * @rcu - for list_del_rcu
+ * @count - number of times this channel is listed in the pool
+ *     (for channels with multiple capabiities)
+ */
+struct dma_chan_ref {
+       struct dma_chan *chan;
+       struct list_head node;
+       struct rcu_head rcu;
+       atomic_t count;
+};
+
+/**
+ * async_tx_flags - modifiers for the async_* calls
+ * @ASYNC_TX_XOR_ZERO_DST: this flag must be used for xor operations where the
+ * the destination address is not a source.  The asynchronous case handles this
+ * implicitly, the synchronous case needs to zero the destination block.
+ * @ASYNC_TX_XOR_DROP_DST: this flag must be used if the destination address is
+ * also one of the source addresses.  In the synchronous case the destination
+ * address is an implied source, whereas the asynchronous case it must be listed
+ * as a source.  The destination address must be the first address in the source
+ * array.
+ * @ASYNC_TX_ASSUME_COHERENT: skip cache maintenance operations
+ * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a
+ * dependency chain
+ * @ASYNC_TX_DEP_ACK: ack the dependency descriptor.  Useful for chaining.
+ * @ASYNC_TX_KMAP_SRC: if the transaction is to be performed synchronously
+ * take an atomic mapping (KM_USER0) on the source page(s)
+ * @ASYNC_TX_KMAP_DST: if the transaction is to be performed synchronously
+ * take an atomic mapping (KM_USER0) on the dest page(s)
+ */
+enum async_tx_flags {
+       ASYNC_TX_XOR_ZERO_DST    = (1 << 0),
+       ASYNC_TX_XOR_DROP_DST    = (1 << 1),
+       ASYNC_TX_ASSUME_COHERENT = (1 << 2),
+       ASYNC_TX_ACK             = (1 << 3),
+       ASYNC_TX_DEP_ACK         = (1 << 4),
+       ASYNC_TX_KMAP_SRC        = (1 << 5),
+       ASYNC_TX_KMAP_DST        = (1 << 6),
+};
+
+#ifdef CONFIG_DMA_ENGINE
+void async_tx_issue_pending_all(void);
+enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
+void async_tx_run_dependencies(struct dma_async_tx_descriptor *tx);
+struct dma_chan *
+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+       enum dma_transaction_type tx_type);
+#else
+static inline void async_tx_issue_pending_all(void)
+{
+       do { } while (0);
+}
+
+static inline enum dma_status
+dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+{
+       return DMA_SUCCESS;
+}
+
+static inline void
+async_tx_run_dependencies(struct dma_async_tx_descriptor *tx,
+       struct dma_chan *host_chan)
+{
+       do { } while (0);
+}
+
+static inline struct dma_chan *
+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+       enum dma_transaction_type tx_type)
+{
+       return NULL;
+}
+#endif
+
+/**
+ * async_tx_sync_epilog - actions to take if an operation is run synchronously
+ * @flags: async_tx flags
+ * @depend_tx: transaction depends on depend_tx
+ * @cb_fn: function to call when the transaction completes
+ * @cb_fn_param: parameter to pass to the callback routine
+ */
+static inline void
+async_tx_sync_epilog(unsigned long flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_fn_param)
+{
+       if (cb_fn)
+               cb_fn(cb_fn_param);
+
+       if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
+               async_tx_ack(depend_tx);
+}
+
+void
+async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+       enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_xor(struct page *dest, struct page **src_list, unsigned int offset,
+       int src_cnt, size_t len, enum async_tx_flags flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_xor_zero_sum(struct page *dest, struct page **src_list,
+       unsigned int offset, int src_cnt, size_t len,
+       u32 *result, enum async_tx_flags flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+       unsigned int src_offset, size_t len, enum async_tx_flags flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_memset(struct page *dest, int val, unsigned int offset,
+       size_t len, enum async_tx_flags flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_trigger_callback(enum async_tx_flags flags,
+       struct dma_async_tx_descriptor *depend_tx,
+       dma_async_tx_callback cb_fn, void *cb_fn_param);
+#endif /* _ASYNC_TX_H_ */
index 407dc7e098bc714e08aaaf4ec5f0862c0eadd728..b5a20162af325094a61edf2417b7a3a6a7c66b1f 100644 (file)
@@ -164,6 +164,8 @@ enum {
        ATA_CMD_SET_MAX         = 0xF9,
        ATA_CMD_SET_MAX_EXT     = 0x37,
        ATA_CMD_READ_LOG_EXT    = 0x2f,
+       ATA_CMD_PMP_READ        = 0xE4,
+       ATA_CMD_PMP_WRITE       = 0xE8,
 
        /* READ_LOG_EXT pages */
        ATA_LOG_SATA_NCQ        = 0x10,
@@ -212,6 +214,28 @@ enum {
                                                   0=to device, 1=to host */
        ATAPI_CDB_LEN           = 16,
 
+       /* PMP stuff */
+       SATA_PMP_MAX_PORTS      = 15,
+       SATA_PMP_CTRL_PORT      = 15,
+
+       SATA_PMP_GSCR_DWORDS    = 128,
+       SATA_PMP_GSCR_PROD_ID   = 0,
+       SATA_PMP_GSCR_REV       = 1,
+       SATA_PMP_GSCR_PORT_INFO = 2,
+       SATA_PMP_GSCR_ERROR     = 32,
+       SATA_PMP_GSCR_ERROR_EN  = 33,
+       SATA_PMP_GSCR_FEAT      = 64,
+       SATA_PMP_GSCR_FEAT_EN   = 96,
+
+       SATA_PMP_PSCR_STATUS    = 0,
+       SATA_PMP_PSCR_ERROR     = 1,
+       SATA_PMP_PSCR_CONTROL   = 2,
+
+       SATA_PMP_FEAT_BIST      = (1 << 0),
+       SATA_PMP_FEAT_PMREQ     = (1 << 1),
+       SATA_PMP_FEAT_DYNSSC    = (1 << 2),
+       SATA_PMP_FEAT_NOTIFY    = (1 << 3),
+
        /* cable types */
        ATA_CBL_NONE            = 0,
        ATA_CBL_PATA40          = 1,
@@ -418,4 +442,9 @@ static inline int lba_48_ok(u64 block, u32 n_block)
        return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
 }
 
+#define sata_pmp_gscr_vendor(gscr)     ((gscr)[SATA_PMP_GSCR_PROD_ID] & 0xffff)
+#define sata_pmp_gscr_devid(gscr)      ((gscr)[SATA_PMP_GSCR_PROD_ID] >> 16)
+#define sata_pmp_gscr_rev(gscr)                (((gscr)[SATA_PMP_GSCR_REV] >> 8) & 0xff)
+#define sata_pmp_gscr_ports(gscr)      ((gscr)[SATA_PMP_GSCR_PORT_INFO] & 0xf)
+
 #endif /* __LINUX_ATA_H__ */
index 5a9c49534d08680cee28276d00f503a896800096..104e51e20e14a56b67e97b868e1bf2847d8b1f91 100644 (file)
@@ -38,6 +38,9 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
 
 void debugfs_remove(struct dentry *dentry);
 
+struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
+                struct dentry *new_dir, const char *new_name);
+
 struct dentry *debugfs_create_u8(const char *name, mode_t mode,
                                 struct dentry *parent, u8 *value);
 struct dentry *debugfs_create_u16(const char *name, mode_t mode,
@@ -85,6 +88,12 @@ static inline struct dentry *debugfs_create_symlink(const char *name,
 static inline void debugfs_remove(struct dentry *dentry)
 { }
 
+static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
+                struct dentry *new_dir, char *new_name)
+{
+       return ERR_PTR(-ENODEV);
+}
+
 static inline struct dentry *debugfs_create_u8(const char *name, mode_t mode,
                                               struct dentry *parent,
                                               u8 *value)
index 2e1a2988b7e15a35240c63a5f56928f2145c2ea2..be2debed70d24d6c4558824be4cbb84ffd0d667d 100644 (file)
@@ -238,7 +238,6 @@ extern int __must_check class_device_create_file(struct class_device *,
  * @devt: for internal use by the driver core only.
  * @node: for internal use by the driver core only.
  * @kobj: for internal use by the driver core only.
- * @devt_attr: for internal use by the driver core only.
  * @groups: optional additional groups to be created
  * @dev: if set, a symlink to the struct device is created in the sysfs
  * directory for this struct class device.
@@ -263,8 +262,6 @@ struct class_device {
        struct kobject          kobj;
        struct class            * class;        /* required */
        dev_t                   devt;           /* dev_t, creates the sysfs "dev" */
-       struct class_device_attribute *devt_attr;
-       struct class_device_attribute uevent_attr;
        struct device           * dev;          /* not necessary, but nice to have */
        void                    * class_data;   /* class-specific data */
        struct class_device     *parent;        /* parent of this child device, if there is one */
@@ -419,8 +416,6 @@ struct device {
        struct device_type      *type;
        unsigned                is_registered:1;
        unsigned                uevent_suppress:1;
-       struct device_attribute uevent_attr;
-       struct device_attribute *devt_attr;
 
        struct semaphore        sem;    /* semaphore to synchronize calls to
                                         * its driver.
index c94d8f1d62e5f297ed4ef39d5c309e86a97e563f..a3b6035b6c860c506c7c5c2d923cdc8444901ad6 100644 (file)
 #ifndef DMAENGINE_H
 #define DMAENGINE_H
 
-#ifdef CONFIG_DMA_ENGINE
-
 #include <linux/device.h>
 #include <linux/uio.h>
 #include <linux/kref.h>
 #include <linux/completion.h>
 #include <linux/rcupdate.h>
+#include <linux/dma-mapping.h>
 
 /**
- * enum dma_event - resource PNP/power managment events
+ * enum dma_state - resource PNP/power managment state
  * @DMA_RESOURCE_SUSPEND: DMA device going into low power state
  * @DMA_RESOURCE_RESUME: DMA device returning to full power
- * @DMA_RESOURCE_ADDED: DMA device added to the system
+ * @DMA_RESOURCE_AVAILABLE: DMA device available to the system
  * @DMA_RESOURCE_REMOVED: DMA device removed from the system
  */
-enum dma_event {
+enum dma_state {
        DMA_RESOURCE_SUSPEND,
        DMA_RESOURCE_RESUME,
-       DMA_RESOURCE_ADDED,
+       DMA_RESOURCE_AVAILABLE,
        DMA_RESOURCE_REMOVED,
 };
 
+/**
+ * enum dma_state_client - state of the channel in the client
+ * @DMA_ACK: client would like to use, or was using this channel
+ * @DMA_DUP: client has already seen this channel, or is not using this channel
+ * @DMA_NAK: client does not want to see any more channels
+ */
+enum dma_state_client {
+       DMA_ACK,
+       DMA_DUP,
+       DMA_NAK,
+};
+
 /**
  * typedef dma_cookie_t - an opaque DMA cookie
  *
@@ -64,6 +75,31 @@ enum dma_status {
        DMA_ERROR,
 };
 
+/**
+ * enum dma_transaction_type - DMA transaction types/indexes
+ */
+enum dma_transaction_type {
+       DMA_MEMCPY,
+       DMA_XOR,
+       DMA_PQ_XOR,
+       DMA_DUAL_XOR,
+       DMA_PQ_UPDATE,
+       DMA_ZERO_SUM,
+       DMA_PQ_ZERO_SUM,
+       DMA_MEMSET,
+       DMA_MEMCPY_CRC32C,
+       DMA_INTERRUPT,
+};
+
+/* last transaction type for creation of the capabilities mask */
+#define DMA_TX_TYPE_END (DMA_INTERRUPT + 1)
+
+/**
+ * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t.
+ * See linux/cpumask.h
+ */
+typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t;
+
 /**
  * struct dma_chan_percpu - the per-CPU part of struct dma_chan
  * @refcount: local_t used for open-coded "bigref" counting
@@ -80,7 +116,6 @@ struct dma_chan_percpu {
 
 /**
  * struct dma_chan - devices supply DMA channels, clients use them
- * @client: ptr to the client user of this chan, will be %NULL when unused
  * @device: ptr to the dma device who supplies this channel, always !%NULL
  * @cookie: last cookie value returned to client
  * @chan_id: channel ID for sysfs
@@ -88,12 +123,10 @@ struct dma_chan_percpu {
  * @refcount: kref, used in "bigref" slow-mode
  * @slow_ref: indicates that the DMA channel is free
  * @rcu: the DMA channel's RCU head
- * @client_node: used to add this to the client chan list
  * @device_node: used to add this to the device chan list
  * @local: per-cpu pointer to a struct dma_chan_percpu
  */
 struct dma_chan {
-       struct dma_client *client;
        struct dma_device *device;
        dma_cookie_t cookie;
 
@@ -105,11 +138,11 @@ struct dma_chan {
        int slow_ref;
        struct rcu_head rcu;
 
-       struct list_head client_node;
        struct list_head device_node;
        struct dma_chan_percpu *local;
 };
 
+
 void dma_chan_cleanup(struct kref *kref);
 
 static inline void dma_chan_get(struct dma_chan *chan)
@@ -134,169 +167,206 @@ static inline void dma_chan_put(struct dma_chan *chan)
 
 /*
  * typedef dma_event_callback - function pointer to a DMA event callback
+ * For each channel added to the system this routine is called for each client.
+ * If the client would like to use the channel it returns '1' to signal (ack)
+ * the dmaengine core to take out a reference on the channel and its
+ * corresponding device.  A client must not 'ack' an available channel more
+ * than once.  When a channel is removed all clients are notified.  If a client
+ * is using the channel it must 'ack' the removal.  A client must not 'ack' a
+ * removed channel more than once.
+ * @client - 'this' pointer for the client context
+ * @chan - channel to be acted upon
+ * @state - available or removed
  */
-typedef void (*dma_event_callback) (struct dma_client *client,
-               struct dma_chan *chan, enum dma_event event);
+struct dma_client;
+typedef enum dma_state_client (*dma_event_callback) (struct dma_client *client,
+               struct dma_chan *chan, enum dma_state state);
 
 /**
  * struct dma_client - info on the entity making use of DMA services
  * @event_callback: func ptr to call when something happens
- * @chan_count: number of chans allocated
- * @chans_desired: number of chans requested. Can be +/- chan_count
- * @lock: protects access to the channels list
- * @channels: the list of DMA channels allocated
+ * @cap_mask: only return channels that satisfy the requested capabilities
+ *  a value of zero corresponds to any capability
  * @global_node: list_head for global dma_client_list
  */
 struct dma_client {
        dma_event_callback      event_callback;
-       unsigned int            chan_count;
-       unsigned int            chans_desired;
-
-       spinlock_t              lock;
-       struct list_head        channels;
+       dma_cap_mask_t          cap_mask;
        struct list_head        global_node;
 };
 
+typedef void (*dma_async_tx_callback)(void *dma_async_param);
+/**
+ * struct dma_async_tx_descriptor - async transaction descriptor
+ * ---dma generic offload fields---
+ * @cookie: tracking cookie for this transaction, set to -EBUSY if
+ *     this tx is sitting on a dependency list
+ * @ack: the descriptor can not be reused until the client acknowledges
+ *     receipt, i.e. has has a chance to establish any dependency chains
+ * @phys: physical address of the descriptor
+ * @tx_list: driver common field for operations that require multiple
+ *     descriptors
+ * @chan: target channel for this operation
+ * @tx_submit: set the prepared descriptor(s) to be executed by the engine
+ * @tx_set_dest: set a destination address in a hardware descriptor
+ * @tx_set_src: set a source address in a hardware descriptor
+ * @callback: routine to call after this operation is complete
+ * @callback_param: general parameter to pass to the callback routine
+ * ---async_tx api specific fields---
+ * @depend_list: at completion this list of transactions are submitted
+ * @depend_node: allow this transaction to be executed after another
+ *     transaction has completed, possibly on another channel
+ * @parent: pointer to the next level up in the dependency chain
+ * @lock: protect the dependency list
+ */
+struct dma_async_tx_descriptor {
+       dma_cookie_t cookie;
+       int ack;
+       dma_addr_t phys;
+       struct list_head tx_list;
+       struct dma_chan *chan;
+       dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);
+       void (*tx_set_dest)(dma_addr_t addr,
+               struct dma_async_tx_descriptor *tx, int index);
+       void (*tx_set_src)(dma_addr_t addr,
+               struct dma_async_tx_descriptor *tx, int index);
+       dma_async_tx_callback callback;
+       void *callback_param;
+       struct list_head depend_list;
+       struct list_head depend_node;
+       struct dma_async_tx_descriptor *parent;
+       spinlock_t lock;
+};
+
 /**
  * struct dma_device - info on the entity supplying DMA services
  * @chancnt: how many DMA channels are supported
  * @channels: the list of struct dma_chan
  * @global_node: list_head for global dma_device_list
+ * @cap_mask: one or more dma_capability flags
+ * @max_xor: maximum number of xor sources, 0 if no capability
  * @refcount: reference count
  * @done: IO completion struct
  * @dev_id: unique device ID
+ * @dev: struct device reference for dma mapping api
  * @device_alloc_chan_resources: allocate resources and return the
  *     number of allocated descriptors
  * @device_free_chan_resources: release DMA channel's resources
- * @device_memcpy_buf_to_buf: memcpy buf pointer to buf pointer
- * @device_memcpy_buf_to_pg: memcpy buf pointer to struct page
- * @device_memcpy_pg_to_pg: memcpy struct page/offset to struct page/offset
- * @device_memcpy_complete: poll the status of an IOAT DMA transaction
- * @device_memcpy_issue_pending: push appended descriptors to hardware
+ * @device_prep_dma_memcpy: prepares a memcpy operation
+ * @device_prep_dma_xor: prepares a xor operation
+ * @device_prep_dma_zero_sum: prepares a zero_sum operation
+ * @device_prep_dma_memset: prepares a memset operation
+ * @device_prep_dma_interrupt: prepares an end of chain interrupt operation
+ * @device_dependency_added: async_tx notifies the channel about new deps
+ * @device_issue_pending: push pending transactions to hardware
  */
 struct dma_device {
 
        unsigned int chancnt;
        struct list_head channels;
        struct list_head global_node;
+       dma_cap_mask_t  cap_mask;
+       int max_xor;
 
        struct kref refcount;
        struct completion done;
 
        int dev_id;
+       struct device *dev;
 
        int (*device_alloc_chan_resources)(struct dma_chan *chan);
        void (*device_free_chan_resources)(struct dma_chan *chan);
-       dma_cookie_t (*device_memcpy_buf_to_buf)(struct dma_chan *chan,
-                       void *dest, void *src, size_t len);
-       dma_cookie_t (*device_memcpy_buf_to_pg)(struct dma_chan *chan,
-                       struct page *page, unsigned int offset, void *kdata,
-                       size_t len);
-       dma_cookie_t (*device_memcpy_pg_to_pg)(struct dma_chan *chan,
-                       struct page *dest_pg, unsigned int dest_off,
-                       struct page *src_pg, unsigned int src_off, size_t len);
-       enum dma_status (*device_memcpy_complete)(struct dma_chan *chan,
+
+       struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
+               struct dma_chan *chan, size_t len, int int_en);
+       struct dma_async_tx_descriptor *(*device_prep_dma_xor)(
+               struct dma_chan *chan, unsigned int src_cnt, size_t len,
+               int int_en);
+       struct dma_async_tx_descriptor *(*device_prep_dma_zero_sum)(
+               struct dma_chan *chan, unsigned int src_cnt, size_t len,
+               u32 *result, int int_en);
+       struct dma_async_tx_descriptor *(*device_prep_dma_memset)(
+               struct dma_chan *chan, int value, size_t len, int int_en);
+       struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
+               struct dma_chan *chan);
+
+       void (*device_dependency_added)(struct dma_chan *chan);
+       enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
                        dma_cookie_t cookie, dma_cookie_t *last,
                        dma_cookie_t *used);
-       void (*device_memcpy_issue_pending)(struct dma_chan *chan);
+       void (*device_issue_pending)(struct dma_chan *chan);
 };
 
 /* --- public DMA engine API --- */
 
-struct dma_client *dma_async_client_register(dma_event_callback event_callback);
+void dma_async_client_register(struct dma_client *client);
 void dma_async_client_unregister(struct dma_client *client);
-void dma_async_client_chan_request(struct dma_client *client,
-               unsigned int number);
+void dma_async_client_chan_request(struct dma_client *client);
+dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
+       void *dest, void *src, size_t len);
+dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
+       struct page *page, unsigned int offset, void *kdata, size_t len);
+dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
+       struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
+       unsigned int src_off, size_t len);
+void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+       struct dma_chan *chan);
 
-/**
- * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
- * @chan: DMA channel to offload copy to
- * @dest: destination address (virtual)
- * @src: source address (virtual)
- * @len: length
- *
- * Both @dest and @src must be mappable to a bus address according to the
- * DMA mapping API rules for streaming mappings.
- * Both @dest and @src must stay memory resident (kernel memory or locked
- * user space pages).
- */
-static inline dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
-       void *dest, void *src, size_t len)
+static inline void
+async_tx_ack(struct dma_async_tx_descriptor *tx)
 {
-       int cpu = get_cpu();
-       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-       put_cpu();
-
-       return chan->device->device_memcpy_buf_to_buf(chan, dest, src, len);
+       tx->ack = 1;
 }
 
-/**
- * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
- * @chan: DMA channel to offload copy to
- * @page: destination page
- * @offset: offset in page to copy to
- * @kdata: source address (virtual)
- * @len: length
- *
- * Both @page/@offset and @kdata must be mappable to a bus address according
- * to the DMA mapping API rules for streaming mappings.
- * Both @page/@offset and @kdata must stay memory resident (kernel memory or
- * locked user space pages)
- */
-static inline dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
-       struct page *page, unsigned int offset, void *kdata, size_t len)
+#define first_dma_cap(mask) __first_dma_cap(&(mask))
+static inline int __first_dma_cap(const dma_cap_mask_t *srcp)
 {
-       int cpu = get_cpu();
-       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-       put_cpu();
+       return min_t(int, DMA_TX_TYPE_END,
+               find_first_bit(srcp->bits, DMA_TX_TYPE_END));
+}
 
-       return chan->device->device_memcpy_buf_to_pg(chan, page, offset,
-                                                    kdata, len);
+#define next_dma_cap(n, mask) __next_dma_cap((n), &(mask))
+static inline int __next_dma_cap(int n, const dma_cap_mask_t *srcp)
+{
+       return min_t(int, DMA_TX_TYPE_END,
+               find_next_bit(srcp->bits, DMA_TX_TYPE_END, n+1));
 }
 
-/**
- * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
- * @chan: DMA channel to offload copy to
- * @dest_pg: destination page
- * @dest_off: offset in page to copy to
- * @src_pg: source page
- * @src_off: offset in page to copy from
- * @len: length
- *
- * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
- * address according to the DMA mapping API rules for streaming mappings.
- * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
- * (kernel memory or locked user space pages).
- */
-static inline dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
-       struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
-       unsigned int src_off, size_t len)
+#define dma_cap_set(tx, mask) __dma_cap_set((tx), &(mask))
+static inline void
+__dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp)
 {
-       int cpu = get_cpu();
-       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-       put_cpu();
+       set_bit(tx_type, dstp->bits);
+}
 
-       return chan->device->device_memcpy_pg_to_pg(chan, dest_pg, dest_off,
-                                                   src_pg, src_off, len);
+#define dma_has_cap(tx, mask) __dma_has_cap((tx), &(mask))
+static inline int
+__dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp)
+{
+       return test_bit(tx_type, srcp->bits);
 }
 
+#define for_each_dma_cap_mask(cap, mask) \
+       for ((cap) = first_dma_cap(mask);       \
+               (cap) < DMA_TX_TYPE_END;        \
+               (cap) = next_dma_cap((cap), (mask)))
+
 /**
- * dma_async_memcpy_issue_pending - flush pending copies to HW
+ * dma_async_issue_pending - flush pending transactions to HW
  * @chan: target DMA channel
  *
  * This allows drivers to push copies to HW in batches,
  * reducing MMIO writes where possible.
  */
-static inline void dma_async_memcpy_issue_pending(struct dma_chan *chan)
+static inline void dma_async_issue_pending(struct dma_chan *chan)
 {
-       return chan->device->device_memcpy_issue_pending(chan);
+       return chan->device->device_issue_pending(chan);
 }
 
+#define dma_async_memcpy_issue_pending(chan) dma_async_issue_pending(chan)
+
 /**
- * dma_async_memcpy_complete - poll for transaction completion
+ * dma_async_is_tx_complete - poll for transaction completion
  * @chan: DMA channel
  * @cookie: transaction identifier to check status of
  * @last: returns last completed cookie, can be NULL
@@ -306,12 +376,15 @@ static inline void dma_async_memcpy_issue_pending(struct dma_chan *chan)
  * internal state and can be used with dma_async_is_complete() to check
  * the status of multiple cookies without re-checking hardware state.
  */
-static inline enum dma_status dma_async_memcpy_complete(struct dma_chan *chan,
+static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
 {
-       return chan->device->device_memcpy_complete(chan, cookie, last, used);
+       return chan->device->device_is_tx_complete(chan, cookie, last, used);
 }
 
+#define dma_async_memcpy_complete(chan, cookie, last, used)\
+       dma_async_is_tx_complete(chan, cookie, last, used)
+
 /**
  * dma_async_is_complete - test a cookie against chan state
  * @cookie: transaction identifier to test status of
@@ -334,6 +407,7 @@ static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie,
        return DMA_IN_PROGRESS;
 }
 
+enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
 
 /* --- DMA device --- */
 
@@ -362,5 +436,4 @@ dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov,
        struct dma_pinned_list *pinned_list, struct page *page,
        unsigned int offset, size_t len);
 
-#endif /* CONFIG_DMA_ENGINE */
 #endif /* DMAENGINE_H */
index 904bf3d2d90bb068bc3837dfc40bf45e65cdddb6..b8ac7b01c45e4964d25ac07cb5c23509ad21621a 100644 (file)
@@ -12,9 +12,17 @@ enum dmi_field {
        DMI_PRODUCT_NAME,
        DMI_PRODUCT_VERSION,
        DMI_PRODUCT_SERIAL,
+       DMI_PRODUCT_UUID,
        DMI_BOARD_VENDOR,
        DMI_BOARD_NAME,
        DMI_BOARD_VERSION,
+       DMI_BOARD_SERIAL,
+       DMI_BOARD_ASSET_TAG,
+       DMI_CHASSIS_VENDOR,
+       DMI_CHASSIS_TYPE,
+       DMI_CHASSIS_VERSION,
+       DMI_CHASSIS_SERIAL,
+       DMI_CHASSIS_ASSET_TAG,
        DMI_STRING_MAX,
 };
 
index b2b3e68aa5128b1076233547627df096e5200ed2..7b647822d6dc67f6d95e003455076e80c98a156c 100644 (file)
 #define EDD_MBR_SIG_MAX 16        /* max number of signatures to store */
 #define EDD_MBR_SIG_NR_BUF 0x1ea  /* addr of number of MBR signtaures at EDD_MBR_SIG_BUF
                                     in boot_params - treat this as 1 byte  */
-#define EDD_CL_EQUALS   0x3d646465     /* "edd=" */
-#define EDD_CL_OFF      0x666f         /* "of" for off  */
-#define EDD_CL_SKIP     0x6b73         /* "sk" for skipmbr */
-#define EDD_CL_ON       0x6e6f        /* "on" for on */
 
 #ifndef __ASSEMBLY__
 
index cae7d618030cbc0e0580a8cb5b9663dd29d2c793..2eaba21b9b1aec6cd9058c9ddbe71a98ed87aaa4 100644 (file)
@@ -90,7 +90,7 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
                                      const u8 *values);
 /* Returns the number of read bytes */
 extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
-                                        u8 command, u8 *values);
+                                        u8 command, u8 length, u8 *values);
 extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
                                          u8 command, u8 length,
                                          const u8 *values);
@@ -150,15 +150,20 @@ struct i2c_driver {
 
 /**
  * struct i2c_client - represent an I2C slave device
+ * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
+ *     I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking
  * @addr: Address used on the I2C bus connected to the parent adapter.
  * @name: Indicates the type of the device, usually a chip name that's
  *     generic enough to hide second-sourcing and compatible revisions.
+ * @adapter: manages the bus segment hosting this I2C device
  * @dev: Driver model device node for the slave.
+ * @irq: indicates the IRQ generated by this device (if any)
  * @driver_name: Identifies new-style driver used with this device; also
  *     used as the module name for hotplug/coldplug modprobe support.
  *
  * An i2c_client identifies a single device (i.e. chip) connected to an
- * i2c bus. The behaviour is defined by the routines of the driver.
+ * i2c bus. The behaviour exposed to Linux is defined by the driver
+ * managing the device.
  */
 struct i2c_client {
        unsigned short flags;           /* div., see below              */
@@ -180,7 +185,8 @@ struct i2c_client {
 
 static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj)
 {
-       return to_i2c_client(container_of(kobj, struct device, kobj));
+       struct device * const dev = container_of(kobj, struct device, kobj);
+       return to_i2c_client(dev);
 }
 
 static inline void *i2c_get_clientdata (struct i2c_client *dev)
@@ -201,7 +207,7 @@ static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
  * @addr: stored in i2c_client.addr
  * @platform_data: stored in i2c_client.dev.platform_data
  * @irq: stored in i2c_client.irq
-
+ *
  * I2C doesn't actually support hardware probing, although controllers and
  * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's
  * a device at a given address.  Drivers commonly need more information than
@@ -210,7 +216,7 @@ static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
  * i2c_board_info is used to build tables of information listing I2C devices
  * that are present.  This information is used to grow the driver model tree
  * for "new style" I2C drivers.  For mainboards this is done statically using
- * i2c_register_board_info(), where @bus_num represents an adapter that isn't
+ * i2c_register_board_info(); bus numbers identify adapters that aren't
  * yet available.  For add-on boards, i2c_new_device() does this dynamically
  * with the adapter already known.
  */
@@ -518,8 +524,9 @@ union i2c_smbus_data {
 #define I2C_SMBUS_WORD_DATA        3
 #define I2C_SMBUS_PROC_CALL        4
 #define I2C_SMBUS_BLOCK_DATA       5
-#define I2C_SMBUS_I2C_BLOCK_DATA    6
+#define I2C_SMBUS_I2C_BLOCK_BROKEN  6
 #define I2C_SMBUS_BLOCK_PROC_CALL   7          /* SMBus 2.0 */
+#define I2C_SMBUS_I2C_BLOCK_DATA    8
 
 
 /* ----- commands for the ioctl like i2c_command call:
index 826803449db7982063c831fc29196f3ce5c3377e..915572fa030b678835732a166b0f7b86e4dc1fb6 100644 (file)
@@ -83,4 +83,33 @@ void idr_remove(struct idr *idp, int id);
 void idr_destroy(struct idr *idp);
 void idr_init(struct idr *idp);
 
+
+/*
+ * IDA - IDR based id allocator, use when translation from id to
+ * pointer isn't necessary.
+ */
+#define IDA_CHUNK_SIZE         128     /* 128 bytes per chunk */
+#define IDA_BITMAP_LONGS       (128 / sizeof(long) - 1)
+#define IDA_BITMAP_BITS                (IDA_BITMAP_LONGS * sizeof(long) * 8)
+
+struct ida_bitmap {
+       long                    nr_busy;
+       unsigned long           bitmap[IDA_BITMAP_LONGS];
+};
+
+struct ida {
+       struct idr              idr;
+       struct ida_bitmap       *free_bitmap;
+};
+
+#define IDA_INIT(name)         { .idr = IDR_INIT(name), .free_bitmap = NULL, }
+#define DEFINE_IDA(name)       struct ida name = IDA_INIT(name)
+
+int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
+int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
+int ida_get_new(struct ida *ida, int *p_id);
+void ida_remove(struct ida *ida, int id);
+void ida_destroy(struct ida *ida);
+void ida_init(struct ida *ida);
+
 #endif /* __IDR_H__ */
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
new file mode 100644 (file)
index 0000000..0d9d7ea
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _LINUX_IF_MACVLAN_H
+#define _LINUX_IF_MACVLAN_H
+
+#ifdef __KERNEL__
+
+extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *);
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_IF_MACVLAN_H */
index 61a57dc2ac994c4a3e20c339ff2bec617d84c532..f8443fdb124a7fc2e6ebc824fc8aac5b1423a80e 100644 (file)
@@ -127,13 +127,6 @@ struct vlan_dev_info {
                                         *   like DHCP that use packet-filtering and don't understand
                                         *   802.1Q
                                         */
-       struct dev_mc_list *old_mc_list;  /* old multi-cast list for the VLAN interface..
-                                           * we save this so we can tell what changes were
-                                           * made, in order to feed the right changes down
-                                           * to the real hardware...
-                                           */
-       int old_allmulti;               /* similar to above. */
-       int old_promiscuity;            /* similar to above. */
        struct net_device *real_dev;    /* the underlying device/interface */
        unsigned char real_dev_addr[ETH_ALEN];
        struct proc_dir_entry *dent;    /* Holds the proc data */
index c288e41ba3315303a47e1614f9790754e8d39b6f..06cbf41d32d258e464fb5263ab1be91e11cf4b43 100644 (file)
@@ -55,7 +55,7 @@ struct kobject {
        struct kobject          * parent;
        struct kset             * kset;
        struct kobj_type        * ktype;
-       struct dentry           * dentry;
+       struct sysfs_dirent     * sd;
        wait_queue_head_t       poll;
 };
 
@@ -71,13 +71,14 @@ extern void kobject_init(struct kobject *);
 extern void kobject_cleanup(struct kobject *);
 
 extern int __must_check kobject_add(struct kobject *);
-extern int __must_check kobject_shadow_add(struct kobject *, struct dentry *);
+extern int __must_check kobject_shadow_add(struct kobject *kobj,
+                                          struct sysfs_dirent *shadow_parent);
 extern void kobject_del(struct kobject *);
 
 extern int __must_check kobject_rename(struct kobject *, const char *new_name);
 extern int __must_check kobject_shadow_rename(struct kobject *kobj,
-                                               struct dentry *new_parent,
-                                               const char *new_name);
+                                             struct sysfs_dirent *new_parent,
+                                             const char *new_name);
 extern int __must_check kobject_move(struct kobject *, struct kobject *);
 
 extern int __must_check kobject_register(struct kobject *);
index a3df64677ac3aa71f46211cbec6ea77470f6edac..47cd2a1c554487b7ae6a028a085b1107c7090712 100644 (file)
@@ -196,7 +196,6 @@ enum {
        ATA_PFLAG_SCSI_HOTPLUG  = (1 << 6), /* SCSI hotplug scheduled */
        ATA_PFLAG_INITIALIZING  = (1 << 7), /* being initialized, don't touch */
 
-       ATA_PFLAG_FLUSH_PORT_TASK = (1 << 16), /* flush port task */
        ATA_PFLAG_SUSPENDED     = (1 << 17), /* port is suspended (power) */
        ATA_PFLAG_PM_PENDING    = (1 << 18), /* PM operation pending */
        ATA_PFLAG_GTM_VALID     = (1 << 19), /* acpi_gtm data valid */
@@ -435,6 +434,7 @@ struct ata_device {
        struct ata_port         *ap;
        unsigned int            devno;          /* 0 or 1 */
        unsigned long           flags;          /* ATA_DFLAG_xxx */
+       unsigned int            horkage;        /* List of broken features */
        struct scsi_device      *sdev;          /* attached SCSI device */
 #ifdef CONFIG_ATA_ACPI
        acpi_handle             acpi_handle;
@@ -466,7 +466,6 @@ struct ata_device {
        /* error history */
        struct ata_ering        ering;
        int                     spdn_cnt;
-       unsigned int            horkage;        /* List of broken features */
 };
 
 /* Offset into struct ata_device.  Fields above it are maintained
@@ -794,7 +793,6 @@ extern void ata_id_string(const u16 *id, unsigned char *s,
 extern void ata_id_c_string(const u16 *id, unsigned char *s,
                            unsigned int ofs, unsigned int len);
 extern void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown);
-extern unsigned long ata_device_blacklisted(const struct ata_device *dev);
 extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
 extern void ata_bmdma_start (struct ata_queued_cmd *qc);
 extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
@@ -871,11 +869,11 @@ struct pci_bits {
        unsigned long           val;
 };
 
-extern int ata_pci_init_native_host(struct ata_host *host);
+extern int ata_pci_init_sff_host(struct ata_host *host);
 extern int ata_pci_init_bmdma(struct ata_host *host);
-extern int ata_pci_prepare_native_host(struct pci_dev *pdev,
-                               const struct ata_port_info * const * ppi,
-                               struct ata_host **r_host);
+extern int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+                                   const struct ata_port_info * const * ppi,
+                                   struct ata_host **r_host);
 extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
 extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long);
 #endif /* CONFIG_PCI */
index 05707e2fccaeda804584da45ee20f0c835b47d22..e2d1ce36b36728084d0d77538dd00b7101d1a528 100644 (file)
@@ -39,6 +39,7 @@
 struct nlm_host {
        struct hlist_node       h_hash;         /* doubly linked list */
        struct sockaddr_in      h_addr;         /* peer address */
+       struct sockaddr_in      h_saddr;        /* our address (optional) */
        struct rpc_clnt *       h_rpcclnt;      /* RPC client to talk to peer */
        char *                  h_name;         /* remote hostname */
        u32                     h_version;      /* interface version */
index b372f5910fc154247e1f1a08b812e606309139e3..cfb78fb2c0460812b1a56cbb78e5a801a8168647 100644 (file)
@@ -172,6 +172,7 @@ struct mlx4_caps {
        int                     num_pds;
        int                     reserved_pds;
        int                     mtt_entry_sz;
+       u32                     max_msg_sz;
        u32                     page_size_cap;
        u32                     flags;
        u16                     stat_rate_support;
@@ -322,6 +323,7 @@ int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
                   u64 db_rec, struct mlx4_srq *srq);
 void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq);
 int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark);
+int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark);
 
 int mlx4_INIT_PORT(struct mlx4_dev *dev, int port);
 int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port);
index 10c57d2791449150c1c721e5b28e11694576292f..3968b943259ae26a5c85fcf2019ab33fad79c958 100644 (file)
@@ -282,6 +282,9 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
                   struct mlx4_qp_context *context, enum mlx4_qp_optpar optpar,
                   int sqd_event, struct mlx4_qp *qp);
 
+int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
+                 struct mlx4_qp_context *context);
+
 static inline struct mlx4_qp *__mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn)
 {
        return radix_tree_lookup(&dev->qp_table_tree, qpn & (dev->caps.num_qps - 1));
index 79cc3dab4be7e8e743dbc3f87f821407effebc99..322b5eae57ddf06192760963e91e1c1e64354873 100644 (file)
@@ -190,6 +190,7 @@ struct dev_addr_list
        struct dev_addr_list    *next;
        u8                      da_addr[MAX_ADDR_LEN];
        u8                      da_addrlen;
+       u8                      da_synced;
        int                     da_users;
        int                     da_gusers;
 };
@@ -516,6 +517,9 @@ struct net_device
                                                void *saddr,
                                                unsigned len);
        int                     (*rebuild_header)(struct sk_buff *skb);
+#define HAVE_CHANGE_RX_FLAGS
+       void                    (*change_rx_flags)(struct net_device *dev,
+                                                  int flags);
 #define HAVE_SET_RX_MODE
        void                    (*set_rx_mode)(struct net_device *dev);
 #define HAVE_MULTICAST                  
@@ -560,6 +564,8 @@ struct net_device
 
        /* bridge stuff */
        struct net_bridge_port  *br_port;
+       /* macvlan */
+       struct macvlan_port     *macvlan_port;
 
        /* class/net/name entry */
        struct device           dev;
@@ -1100,6 +1106,8 @@ extern int                dev_unicast_delete(struct net_device *dev, void *addr, int alen);
 extern int             dev_unicast_add(struct net_device *dev, void *addr, int alen);
 extern int             dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
 extern int             dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
+extern int             dev_mc_sync(struct net_device *to, struct net_device *from);
+extern void            dev_mc_unsync(struct net_device *to, struct net_device *from);
 extern void            dev_mc_discard(struct net_device *dev);
 extern int             __dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all);
 extern int             __dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly);
index 7e7f33a38fc06ba6b06929a9f1e94f77e6b09cae..8726491de15417d882d36e3184159f79c0bf525e 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/types.h>
 
+#define NFS4_BITMAP_SIZE       2
 #define NFS4_VERIFIER_SIZE     8
 #define NFS4_STATEID_SIZE      16
 #define NFS4_FHSIZE            128
index 26b4c83f831dee1adbcbca9cc1c3d378720ad419..a0dcf66556571762c0715551da7d2023d0cbe980 100644 (file)
@@ -65,6 +65,7 @@ struct nfs4_mount_data {
 #define NFS4_MOUNT_NOCTO       0x0010  /* 1 */
 #define NFS4_MOUNT_NOAC                0x0020  /* 1 */
 #define NFS4_MOUNT_STRICTLOCK  0x1000  /* 1 */
-#define NFS4_MOUNT_FLAGMASK    0xFFFF
+#define NFS4_MOUNT_UNSHARED    0x8000  /* 1 */
+#define NFS4_MOUNT_FLAGMASK    0x9033
 
 #endif
index 0543439a97aff58b508ce54af24111b1145a7eee..c098ae194f79daf0c498a7aec7e3eb24186d24c5 100644 (file)
@@ -30,7 +30,9 @@
 #ifdef __KERNEL__
 
 #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>
@@ -69,9 +71,8 @@ struct nfs_access_entry {
 
 struct nfs4_state;
 struct nfs_open_context {
-       atomic_t count;
-       struct vfsmount *vfsmnt;
-       struct dentry *dentry;
+       struct kref kref;
+       struct path path;
        struct rpc_cred *cred;
        struct nfs4_state *state;
        fl_owner_t lockowner;
@@ -155,13 +156,9 @@ struct nfs_inode {
        /*
         * This is the list of dirty unwritten pages.
         */
-       spinlock_t              req_lock;
-       struct list_head        dirty;
-       struct list_head        commit;
        struct radix_tree_root  nfs_page_tree;
 
-       unsigned int            ndirty,
-                               ncommit,
+       unsigned long           ncommit,
                                npages;
 
        /* Open contexts for shared mmap writes */
@@ -187,6 +184,7 @@ struct nfs_inode {
 #define NFS_INO_INVALID_ACCESS 0x0008          /* cached access cred invalid */
 #define NFS_INO_INVALID_ACL    0x0010          /* cached acls are invalid */
 #define NFS_INO_REVAL_PAGECACHE        0x0020          /* must revalidate pagecache */
+#define NFS_INO_REVAL_FORCED   0x0040          /* force revalidation ignoring a delegation */
 
 /*
  * Bit offsets in flags field
@@ -496,21 +494,18 @@ static inline void nfs3_forget_cached_acls(struct inode *inode)
 
 /*
  * linux/fs/mount_clnt.c
- * (Used only by nfsroot module)
  */
-extern int  nfsroot_mount(struct sockaddr_in *, char *, struct nfs_fh *,
-               int, int);
+extern int  nfs_mount(struct sockaddr *, size_t, char *, char *,
+                     int, int, struct nfs_fh *);
 
 /*
  * inline functions
  */
 
-static inline loff_t
-nfs_size_to_loff_t(__u64 size)
+static inline loff_t nfs_size_to_loff_t(__u64 size)
 {
-       loff_t maxsz = (((loff_t) ULONG_MAX) << PAGE_CACHE_SHIFT) + PAGE_CACHE_SIZE - 1;
-       if (size > maxsz)
-               return maxsz;
+       if (size > (__u64) OFFSET_MAX - 1)
+               return OFFSET_MAX - 1;
        return (loff_t) size;
 }
 
@@ -557,6 +552,7 @@ extern void * nfs_root_data(void);
 #define NFSDBG_ROOT            0x0080
 #define NFSDBG_CALLBACK                0x0100
 #define NFSDBG_CLIENT          0x0200
+#define NFSDBG_MOUNT           0x0400
 #define NFSDBG_ALL             0xFFFF
 
 #ifdef __KERNEL__
index 52b4378311c86393e04038d17eb1f9466f980bc5..0cac49bc09553ef33b572593f038bb0e198fb17d 100644 (file)
@@ -16,7 +16,6 @@ struct nfs_client {
 #define NFS_CS_INITING         1               /* busy initialising */
        int                     cl_nfsversion;  /* NFS protocol version */
        unsigned long           cl_res_state;   /* NFS resources state */
-#define NFS_CS_RPCIOD          0               /* - rpciod started */
 #define NFS_CS_CALLBACK                1               /* - callback started */
 #define NFS_CS_IDMAP           2               /* - idmap started */
 #define NFS_CS_RENEWD          3               /* - renewd started */
@@ -35,7 +34,8 @@ struct nfs_client {
        nfs4_verifier           cl_confirm;
        unsigned long           cl_state;
 
-       u32                     cl_lockowner_id;
+       struct rb_root          cl_openowner_id;
+       struct rb_root          cl_lockowner_id;
 
        /*
         * The following rwsem ensures exclusive access to the server
@@ -44,9 +44,7 @@ struct nfs_client {
        struct rw_semaphore     cl_sem;
 
        struct list_head        cl_delegations;
-       struct list_head        cl_state_owners;
-       struct list_head        cl_unused;
-       int                     cl_nunused;
+       struct rb_root          cl_state_owners;
        spinlock_t              cl_lock;
 
        unsigned long           cl_lease_time;
index cc8b9c59acb8607005e7a891efbb74b29ac6a994..a3ade89a64d21f68c359d35d5b179d97a93c0fcc 100644 (file)
@@ -37,7 +37,7 @@ struct nfs_mount_data {
        int             acdirmin;               /* 1 */
        int             acdirmax;               /* 1 */
        struct sockaddr_in addr;                /* 1 */
-       char            hostname[256];          /* 1 */
+       char            hostname[NFS_MAXNAMLEN + 1];            /* 1 */
        int             namlen;                 /* 2 */
        unsigned int    bsize;                  /* 3 */
        struct nfs3_fh  root;                   /* 4 */
@@ -62,6 +62,7 @@ struct nfs_mount_data {
 #define NFS_MOUNT_STRICTLOCK   0x1000  /* reserved for NFSv4 */
 #define NFS_MOUNT_SECFLAVOUR   0x2000  /* 5 */
 #define NFS_MOUNT_NORDIRPLUS   0x4000  /* 5 */
+#define NFS_MOUNT_UNSHARED     0x8000  /* 5 */
 #define NFS_MOUNT_FLAGMASK     0xFFFF
 
 #endif
index bd193af801629a95bdc2c45ef201d84305b25b61..78e60798d10e39c513fe9978677dd67d9578d4a3 100644 (file)
 #include <linux/sunrpc/auth.h>
 #include <linux/nfs_xdr.h>
 
-#include <asm/atomic.h>
+#include <linux/kref.h>
 
 /*
  * Valid flags for the radix tree
  */
-#define NFS_PAGE_TAG_WRITEBACK 0
+#define NFS_PAGE_TAG_LOCKED    0
+#define NFS_PAGE_TAG_COMMIT    1
 
 /*
  * Valid flags for a dirty buffer
@@ -33,8 +34,7 @@
 
 struct nfs_inode;
 struct nfs_page {
-       struct list_head        wb_list,        /* Defines state of page: */
-                               *wb_list_head;  /*      read/write/commit */
+       struct list_head        wb_list;        /* Defines state of page: */
        struct page             *wb_page;       /* page to read in/write out */
        struct nfs_open_context *wb_context;    /* File state context info */
        atomic_t                wb_complete;    /* i/os we're waiting for */
@@ -42,7 +42,7 @@ struct nfs_page {
        unsigned int            wb_offset,      /* Offset & ~PAGE_CACHE_MASK */
                                wb_pgbase,      /* Start of page data */
                                wb_bytes;       /* Length of request */
-       atomic_t                wb_count;       /* reference count */
+       struct kref             wb_kref;        /* reference count */
        unsigned long           wb_flags;
        struct nfs_writeverf    wb_verf;        /* Commit cookie */
 };
@@ -71,8 +71,8 @@ extern        void nfs_clear_request(struct nfs_page *req);
 extern void nfs_release_request(struct nfs_page *req);
 
 
-extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst,
-                         pgoff_t idx_start, unsigned int npages);
+extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *dst,
+                         pgoff_t idx_start, unsigned int npages, int tag);
 extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
                             struct inode *inode,
                             int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
@@ -84,12 +84,11 @@ extern      void nfs_pageio_complete(struct nfs_pageio_descriptor *desc);
 extern void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t);
 extern  int nfs_wait_on_request(struct nfs_page *);
 extern void nfs_unlock_request(struct nfs_page *req);
-extern  int nfs_set_page_writeback_locked(struct nfs_page *req);
-extern  void nfs_clear_page_writeback(struct nfs_page *req);
+extern  void nfs_clear_page_tag_locked(struct nfs_page *req);
 
 
 /*
- * Lock the page of an asynchronous request without incrementing the wb_count
+ * Lock the page of an asynchronous request without getting a new reference
  */
 static inline int
 nfs_lock_request_dontget(struct nfs_page *req)
@@ -98,14 +97,14 @@ nfs_lock_request_dontget(struct nfs_page *req)
 }
 
 /*
- * Lock the page of an asynchronous request
+ * Lock the page of an asynchronous request and take a reference
  */
 static inline int
 nfs_lock_request(struct nfs_page *req)
 {
        if (test_and_set_bit(PG_BUSY, &req->wb_flags))
                return 0;
-       atomic_inc(&req->wb_count);
+       kref_get(&req->wb_kref);
        return 1;
 }
 
@@ -118,7 +117,6 @@ static inline void
 nfs_list_add_request(struct nfs_page *req, struct list_head *head)
 {
        list_add_tail(&req->wb_list, head);
-       req->wb_list_head = head;
 }
 
 
@@ -132,7 +130,6 @@ nfs_list_remove_request(struct nfs_page *req)
        if (list_empty(&req->wb_list))
                return;
        list_del_init(&req->wb_list);
-       req->wb_list_head = NULL;
 }
 
 static inline struct nfs_page *
index 10c26ed0db7129831d42b109f2aa2bbc222f0286..38d77681cf2796b5343f7e419ed769374ca368f4 100644 (file)
@@ -119,7 +119,7 @@ struct nfs_openargs {
        struct nfs_seqid *      seqid;
        int                     open_flags;
        __u64                   clientid;
-       __u32                   id;
+       __u64                   id;
        union {
                struct iattr *  attrs;    /* UNCHECKED, GUARDED */
                nfs4_verifier   verifier; /* EXCLUSIVE */
@@ -144,6 +144,7 @@ struct nfs_openres {
        nfs4_stateid            delegation;
        __u32                   do_recall;
        __u64                   maxsize;
+       __u32                   attrset[NFS4_BITMAP_SIZE];
 };
 
 /*
@@ -180,7 +181,7 @@ struct nfs_closeres {
  *   */
 struct nfs_lowner {
        __u64                   clientid;
-       u32                     id;
+       __u64                   id;
 };
 
 struct nfs_lock_args {
index 086a0e5a6318ecad38b36a2b5d57f47ceb336695..37a71580ad8a4f8b9e099e1e6e51b155ef50526b 100644 (file)
@@ -111,7 +111,8 @@ enum pcie_reset_state {
 
 typedef unsigned short __bitwise pci_bus_flags_t;
 enum pci_bus_flags {
-       PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
+       PCI_BUS_FLAGS_NO_MSI   = (__force pci_bus_flags_t) 1,
+       PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2,
 };
 
 struct pci_cap_saved_state {
@@ -138,6 +139,7 @@ struct pci_dev {
        unsigned short  subsystem_vendor;
        unsigned short  subsystem_device;
        unsigned int    class;          /* 3 bytes: (base,sub,prog-if) */
+       u8              revision;       /* PCI revision, low byte of class word */
        u8              hdr_type;       /* PCI header type (`multi' flag masked out) */
        u8              rom_base_reg;   /* which config register controls the ROM */
        u8              pin;            /* which interrupt pin this device uses */
@@ -313,7 +315,7 @@ struct pci_dynids {
 
 /* ---------------------------------------------------------------- */
 /** PCI Error Recovery System (PCI-ERS).  If a PCI device driver provides
- *  a set fof callbacks in struct pci_error_handlers, then that device driver
+ *  a set of callbacks in struct pci_error_handlers, then that device driver
  *  will be notified of PCI bus errors, and will be driven to recovery
  *  when an error occurs.
  */
@@ -370,7 +372,6 @@ struct pci_driver {
        int  (*suspend_late) (struct pci_dev *dev, pm_message_t state);
        int  (*resume_early) (struct pci_dev *dev);
        int  (*resume) (struct pci_dev *dev);                   /* Device woken up */
-       int  (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable);   /* Enable wake event */
        void (*shutdown) (struct pci_dev *dev);
 
        struct pci_error_handlers *err_handler;
@@ -475,7 +476,7 @@ extern void pci_sort_breadthfirst(void);
 /* Generic PCI functions exported to card drivers */
 
 struct pci_dev __deprecated *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from);
-struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
+struct pci_dev __deprecated *pci_find_slot (unsigned int bus, unsigned int devfn);
 int pci_find_capability (struct pci_dev *dev, int cap);
 int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
 int pci_find_ext_capability (struct pci_dev *dev, int cap);
@@ -544,11 +545,16 @@ void pci_set_master(struct pci_dev *dev);
 int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state);
 #define HAVE_PCI_SET_MWI
 int __must_check pci_set_mwi(struct pci_dev *dev);
+int pci_try_set_mwi(struct pci_dev *dev);
 void pci_clear_mwi(struct pci_dev *dev);
 void pci_intx(struct pci_dev *dev, int enable);
 void pci_msi_off(struct pci_dev *dev);
 int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
 int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
+int pcix_get_max_mmrbc(struct pci_dev *dev);
+int pcix_get_mmrbc(struct pci_dev *dev);
+int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc);
+int pcie_set_readrq(struct pci_dev *dev, int rq);
 void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
 int __must_check pci_assign_resource(struct pci_dev *dev, int i);
 int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i);
@@ -560,6 +566,7 @@ void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
 void __iomem __must_check *pci_map_rom_copy(struct pci_dev *pdev, size_t *size);
 void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
 void pci_remove_rom(struct pci_dev *pdev);
+size_t pci_get_rom_size(void __iomem *rom, size_t size);
 
 /* Power management related routines */
 int pci_save_state(struct pci_dev *dev);
@@ -876,5 +883,7 @@ extern int pci_pci_problems;
 extern unsigned long pci_cardbus_io_size;
 extern unsigned long pci_cardbus_mem_size;
 
+extern int pcibios_add_platform_entries(struct pci_dev *dev);
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
index 75c4d4d068928158bb357885dae780bafad0e92c..2c7add169539125490ed5222822703f72c750d36 100644 (file)
 
 /* Vendors and devices.  Sort key: vendor first, device next. */
 
+#define PCI_VENDOR_ID_TTTECH           0x0357
+#define PCI_DEVICE_ID_TTTECH_MC322     0x000a
+
 #define PCI_VENDOR_ID_DYNALINK         0x0675
 #define PCI_DEVICE_ID_DYNALINK_IS64PH  0x1702
 
 #define PCI_DEVICE_ID_ATI_IXP600_SMBUS 0x4385
 #define PCI_DEVICE_ID_ATI_IXP600_IDE   0x438c
 #define PCI_DEVICE_ID_ATI_IXP700_SATA  0x4390
+#define PCI_DEVICE_ID_ATI_IXP700_SMBUS 0x4395
 #define PCI_DEVICE_ID_ATI_IXP700_IDE   0x439c
 
 #define PCI_VENDOR_ID_VLSI             0x1004
 #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
 #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
 
+#define PCI_VENDOR_ID_UNISYS           0x1018
+#define PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR 0x001C
+
 #define PCI_VENDOR_ID_COMPEX2          0x101a /* pci.ids says "AT&T GIS (NCR)" */
 #define PCI_DEVICE_ID_COMPEX2_100VG    0x0005
 
 #define PCI_DEVICE_ID_ELSA_MICROLINK   0x1000
 #define PCI_DEVICE_ID_ELSA_QS3000      0x3000
 
-
 #define PCI_VENDOR_ID_BUSLOGIC               0x104B
 #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
 #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER    0x1040
 
 #define PCI_VENDOR_ID_SONY             0x104d
 
-
 /* Winbond have two vendor IDs! See 0x10ad as well */
 #define PCI_VENDOR_ID_WINBOND2         0x1050
 #define PCI_DEVICE_ID_WINBOND2_89C940F 0x5a5a
 #define PCI_DEVICE_ID_PROMISE_20276    0x5275
 #define PCI_DEVICE_ID_PROMISE_20277    0x7275
 
-
 #define PCI_VENDOR_ID_UMC              0x1060
 #define PCI_DEVICE_ID_UMC_UM8673F      0x0101
 #define PCI_DEVICE_ID_UMC_UM8886BF     0x673a
 #define PCI_DEVICE_ID_MYLEX_DAC960_BA  0xBA56
 #define PCI_DEVICE_ID_MYLEX_DAC960_GEM 0xB166
 
-
 #define PCI_VENDOR_ID_APPLE            0x106b
 #define PCI_DEVICE_ID_APPLE_BANDIT     0x0001
 #define PCI_DEVICE_ID_APPLE_HYDRA      0x000e
 #define PCI_DEVICE_ID_YAMAHA_744       0x0010
 #define PCI_DEVICE_ID_YAMAHA_754       0x0012
 
-
 #define PCI_VENDOR_ID_QLOGIC           0x1077
 #define PCI_DEVICE_ID_QLOGIC_ISP10160  0x1016
 #define PCI_DEVICE_ID_QLOGIC_ISP1020   0x1020
 #define PCI_DEVICE_ID_CYRIX_5530_AUDIO 0x0103
 #define PCI_DEVICE_ID_CYRIX_5530_VIDEO 0x0104
 
-
-
 #define PCI_VENDOR_ID_CONTAQ           0x1080
 #define PCI_DEVICE_ID_CONTAQ_82C693    0xc693
 
-
 #define PCI_VENDOR_ID_OLICOM           0x108d
 #define PCI_DEVICE_ID_OLICOM_OC2325    0x0012
 #define PCI_DEVICE_ID_OLICOM_OC2183    0x0013
 #define PCI_DEVICE_ID_SII_3112         0x3112
 #define PCI_DEVICE_ID_SII_1210SA       0x0240
 
-
 #define PCI_VENDOR_ID_BROOKTREE                0x109e
 #define PCI_DEVICE_ID_BROOKTREE_878    0x0878
 #define PCI_DEVICE_ID_BROOKTREE_879    0x0879
 
-
 #define PCI_VENDOR_ID_SGI              0x10a9
 #define PCI_DEVICE_ID_SGI_IOC3         0x0003
+#define PCI_DEVICE_ID_SGI_LITHIUM      0x1002
 #define PCI_DEVICE_ID_SGI_IOC4         0x100a
-#define PCI_VENDOR_ID_SGI_LITHIUM      0x1002
-
 
 #define PCI_VENDOR_ID_WINBOND          0x10ad
 #define PCI_DEVICE_ID_WINBOND_82C105   0x0105
 #define PCI_DEVICE_ID_WINBOND_83C553   0x0565
 
-
 #define PCI_VENDOR_ID_PLX              0x10b5
 #define PCI_DEVICE_ID_PLX_R685         0x1030
 #define PCI_DEVICE_ID_PLX_ROMULUS      0x106a
 #define PCI_DEVICE_ID_3COM_3CR990SVR97 0x9909
 #define PCI_DEVICE_ID_3COM_3CR990SVR   0x990a
 
-
 #define PCI_VENDOR_ID_AL               0x10b9
 #define PCI_DEVICE_ID_AL_M1533         0x1533
 #define PCI_DEVICE_ID_AL_M1535                 0x1535
 #define PCI_DEVICE_ID_AL_M5451         0x5451
 #define PCI_DEVICE_ID_AL_M7101         0x7101
 
-
-
 #define PCI_VENDOR_ID_NEOMAGIC         0x10c8
 #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
 #define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
 #define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
 
-
 #define PCI_VENDOR_ID_TCONRAD          0x10da
 #define PCI_DEVICE_ID_TCONRAD_TOKENRING        0x0508
 
-
 #define PCI_VENDOR_ID_NVIDIA                   0x10de
 #define PCI_DEVICE_ID_NVIDIA_TNT               0x0020
 #define PCI_DEVICE_ID_NVIDIA_TNT2              0x0028
 #define PCI_DEVICE_ID_IMS_TT128                0x9128
 #define PCI_DEVICE_ID_IMS_TT3D         0x9135
 
-
-
-
 #define PCI_VENDOR_ID_INTERG           0x10ea
 #define PCI_DEVICE_ID_INTERG_1682      0x1682
 #define PCI_DEVICE_ID_INTERG_2000      0x2000
 #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
 #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
 
-
 #define PCI_VENDOR_ID_INIT             0x1101
 
 #define PCI_VENDOR_ID_CREATIVE         0x1102 /* duplicate: ECTIVA */
 #define PCI_VENDOR_ID_SIEMENS           0x110A
 #define PCI_DEVICE_ID_SIEMENS_DSCC4     0x2102
 
-
 #define PCI_VENDOR_ID_VORTEX           0x1119
 #define PCI_DEVICE_ID_VORTEX_GDT60x0   0x0000
 #define PCI_DEVICE_ID_VORTEX_GDT6000B  0x0001
 #define PCI_VENDOR_ID_EF               0x111a
 #define PCI_DEVICE_ID_EF_ATM_FPGA      0x0000
 #define PCI_DEVICE_ID_EF_ATM_ASIC      0x0002
-#define PCI_VENDOR_ID_EF_ATM_LANAI2    0x0003
-#define PCI_VENDOR_ID_EF_ATM_LANAIHB   0x0005
+#define PCI_DEVICE_ID_EF_ATM_LANAI2    0x0003
+#define PCI_DEVICE_ID_EF_ATM_LANAIHB   0x0005
 
 #define PCI_VENDOR_ID_IDT              0x111d
 #define PCI_DEVICE_ID_IDT_IDT77201     0x0001
 #define PCI_VENDOR_ID_FORE             0x1127
 #define PCI_DEVICE_ID_FORE_PCA200E     0x0300
 
-
 #define PCI_VENDOR_ID_PHILIPS          0x1131
 #define PCI_DEVICE_ID_PHILIPS_SAA7146  0x7146
 #define PCI_DEVICE_ID_PHILIPS_SAA9730  0x9730
 #define PCI_DEVICE_ID_ZIATECH_5550_HC  0x5550
  
 
-
 #define PCI_VENDOR_ID_SYSKONNECT       0x1148
 #define PCI_DEVICE_ID_SYSKONNECT_TR    0x4200
 #define PCI_DEVICE_ID_SYSKONNECT_GE    0x4300
 #define PCI_DEVICE_ID_SYSKONNECT_9DXX  0x4400
 #define PCI_DEVICE_ID_SYSKONNECT_9MXX  0x4500
 
-
 #define PCI_VENDOR_ID_DIGI             0x114f
 #define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070
 #define PCI_DEVICE_ID_DIGI_DF_M_E      0x0071
 #define PCI_DEVICE_ID_NEO_2RJ45         0x00CA
 #define PCI_DEVICE_ID_NEO_2RJ45PRI      0x00CB
 
-
 #define PCI_VENDOR_ID_XIRCOM           0x115d
 #define PCI_DEVICE_ID_XIRCOM_RBM56G    0x0101
 #define PCI_DEVICE_ID_XIRCOM_X3201_MDM 0x0103
 
-
 #define PCI_VENDOR_ID_SERVERWORKS        0x1166
 #define PCI_DEVICE_ID_SERVERWORKS_HE     0x0008
 #define PCI_DEVICE_ID_SERVERWORKS_LE     0x0009
 #define PCI_DEVICE_ID_ZEITNET_1221     0x0001
 #define PCI_DEVICE_ID_ZEITNET_1225     0x0002
 
-
 #define PCI_VENDOR_ID_FUJITSU_ME       0x119e
 #define PCI_DEVICE_ID_FUJITSU_FS155    0x0001
 #define PCI_DEVICE_ID_FUJITSU_FS50     0x0003
 #define PCI_DEVICE_ID_V3_V960          0x0001
 #define PCI_DEVICE_ID_V3_V351          0x0002
 
-
 #define PCI_VENDOR_ID_ATT              0x11c1
 #define PCI_DEVICE_ID_ATT_VENUS_MODEM  0x480
 
-
 #define PCI_VENDOR_ID_SPECIALIX                0x11cb
 #define PCI_DEVICE_ID_SPECIALIX_IO8    0x2000
 #define PCI_DEVICE_ID_SPECIALIX_RIO    0x8000
 #define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004
 
-
 #define PCI_VENDOR_ID_ANALOG_DEVICES   0x11d4
 #define PCI_DEVICE_ID_AD1889JS         0x1889
 
-
 #define PCI_DEVICE_ID_SEGA_BBA         0x1234
 
 #define PCI_VENDOR_ID_ZORAN            0x11de
 #define PCI_DEVICE_ID_ZORAN_36057      0x6057
 #define PCI_DEVICE_ID_ZORAN_36120      0x6120
 
-
 #define PCI_VENDOR_ID_COMPEX           0x11f6
 #define PCI_DEVICE_ID_COMPEX_ENET100VG4        0x0112
 
 #define PCI_DEVICE_ID_3DFX_VOODOO3     0x0005
 #define PCI_DEVICE_ID_3DFX_VOODOO5     0x0009
 
-
-
 #define PCI_VENDOR_ID_AVM              0x1244
 #define PCI_DEVICE_ID_AVM_B1           0x0700
 #define PCI_DEVICE_ID_AVM_C4           0x0800
 #define PCI_DEVICE_ID_AVM_C2           0x1100
 #define PCI_DEVICE_ID_AVM_T1           0x1200
 
-
 #define PCI_VENDOR_ID_STALLION         0x124d
 
 /* Allied Telesyn */
 #define PCI_VENDOR_ID_SATSAGEM         0x1267
 #define PCI_DEVICE_ID_SATSAGEM_NICCY   0x1016
 
-
 #define PCI_VENDOR_ID_ENSONIQ          0x1274
 #define PCI_DEVICE_ID_ENSONIQ_CT5880   0x5880
 #define PCI_DEVICE_ID_ENSONIQ_ES1370   0x5000
 
 #define PCI_VENDOR_ID_ALTEON           0x12ae
 
-
 #define PCI_SUBVENDOR_ID_CONNECT_TECH                  0x12c4
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232          0x0001
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232          0x0002
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485   0x0331
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485   0x0332
 
-
 #define PCI_VENDOR_ID_NVIDIA_SGS       0x12d2
 #define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
 
 #define PCI_DEVICE_ID_LMC_SSI          0x0005
 #define PCI_DEVICE_ID_LMC_T1           0x0006
 
-
 #define PCI_VENDOR_ID_NETGEAR          0x1385
 #define PCI_DEVICE_ID_NETGEAR_GA620    0x620a
 
 #define PCI_DEVICE_ID_OXSEMI_16PCI952  0x9521
 #define PCI_DEVICE_ID_OXSEMI_16PCI952PP        0x9523
 
+#define PCI_VENDOR_ID_CHELSIO          0x1425
+
 #define PCI_VENDOR_ID_SAMSUNG          0x144d
 
 #define PCI_VENDOR_ID_MYRICOM          0x14c1
 #define PCI_DEVICE_ID_ENE_720          0x1421
 #define PCI_DEVICE_ID_ENE_722          0x1422
 
-#define PCI_VENDOR_ID_CHELSIO          0x1425
-
 #define PCI_SUBVENDOR_ID_PERLE          0x155f
 #define PCI_SUBDEVICE_ID_PCI_RAS4       0xf001
 #define PCI_SUBDEVICE_ID_PCI_RAS8       0xf010
 
-
 #define PCI_VENDOR_ID_SYBA             0x1592
 #define PCI_DEVICE_ID_SYBA_2P_EPP      0x0782
 #define PCI_DEVICE_ID_SYBA_1P_ECP      0x0783
 #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
 #define PCI_DEVICE_ID_MELLANOX_SINAI   0x6274
 
-#define PCI_VENDOR_ID_PDC              0x15e9
+#define PCI_VENDOR_ID_QUICKNET         0x15e2
+#define PCI_DEVICE_ID_QUICKNET_XJ      0x0500
 
+#define PCI_VENDOR_ID_PDC              0x15e9
 
 #define PCI_VENDOR_ID_FARSITE           0x1619
 #define PCI_DEVICE_ID_FARSITE_T2P       0x0400
 #define PCI_DEVICE_ID_BCM1250_PCI      0x0001
 #define PCI_DEVICE_ID_BCM1250_HT       0x0002
 
+#define PCI_VENDOR_ID_ATHEROS          0x168c
+
 #define PCI_VENDOR_ID_NETCELL          0x169c
 #define PCI_DEVICE_ID_REVOLUTION       0x0044
 
 #define PCI_DEVICE_ID_HERC_WIN         0x5732
 #define PCI_DEVICE_ID_HERC_UNI         0x5832
 
-
 #define PCI_VENDOR_ID_SITECOM          0x182d
 #define PCI_DEVICE_ID_SITECOM_DC105V2  0x3069
 
 #define PCI_DEVICE_ID_3DLABS_PERMEDIA2 0x0007
 #define PCI_DEVICE_ID_3DLABS_PERMEDIA2V        0x0009
 
-
 #define PCI_VENDOR_ID_AKS              0x416c
 #define PCI_DEVICE_ID_AKS_ALADDINCARD  0x0100
 
-
-
 #define PCI_VENDOR_ID_S3               0x5333
 #define PCI_DEVICE_ID_S3_TRIO          0x8811
 #define PCI_DEVICE_ID_S3_868           0x8880
 #define PCI_VENDOR_ID_DUNORD           0x5544
 #define PCI_DEVICE_ID_DUNORD_I3000     0x0001
 
-
 #define PCI_VENDOR_ID_DCI              0x6666
 #define PCI_DEVICE_ID_DCI_PCCOM4       0x0001
 #define PCI_DEVICE_ID_DCI_PCCOM8       0x0002
 #define PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN   0x0500
 #define PCI_DEVICE_ID_ADAPTEC2_SCAMP   0x0503
 
-
 #define PCI_VENDOR_ID_HOLTEK           0x9412
 #define PCI_DEVICE_ID_HOLTEK_6565      0x6565
 
 #define PCI_DEVICE_ID_NETMOS_9845      0x9845
 #define PCI_DEVICE_ID_NETMOS_9855      0x9855
 
+#define PCI_VENDOR_ID_3COM_2           0xa727
+
 #define PCI_SUBVENDOR_ID_EXSYS         0xd84d
 #define PCI_SUBDEVICE_ID_EXSYS_4014    0x4014
 #define PCI_SUBDEVICE_ID_EXSYS_4055    0x4055
 #define PCI_DEVICE_ID_TIGERJET_300     0x0001
 #define PCI_DEVICE_ID_TIGERJET_100     0x0002
 
-#define PCI_VENDOR_ID_TTTECH           0x0357
-#define PCI_DEVICE_ID_TTTECH_MC322     0x000A
-
 #define PCI_VENDOR_ID_XILINX_RME       0xea60
 #define PCI_DEVICE_ID_RME_DIGI32       0x9896
 #define PCI_DEVICE_ID_RME_DIGI32_PRO   0x9897
 #define PCI_DEVICE_ID_RME_DIGI32_8     0x9898
-
-#define PCI_VENDOR_ID_QUICKNET         0x15E2
-#define PCI_DEVICE_ID_QUICKNET_XJ      0x0500
index b2c4fde4e994934b21b4438090bec8f446d2e2e8..273781c82e4dd1551ad41b4550b6bb1dcda1f4a1 100644 (file)
@@ -267,15 +267,10 @@ struct dev_pm_info {
        unsigned                can_wakeup:1;
 #ifdef CONFIG_PM
        unsigned                should_wakeup:1;
-       pm_message_t            prev_state;
-       void                    * saved_state;
-       struct device           * pm_parent;
        struct list_head        entry;
 #endif
 };
 
-extern void device_pm_set_parent(struct device * dev, struct device * parent);
-
 extern int device_power_down(pm_message_t state);
 extern void device_power_up(void);
 extern void device_resume(void);
index d8286db60b96572153a9f22ec94f0b91ef7ff41a..93678f57ccbe280d3b681aa5c31a2c5049c32a6a 100644 (file)
  *  attach a request to an active stripe (add_stripe_bh())
  *     lockdev attach-buffer unlockdev
  *  handle a stripe (handle_stripe())
- *     lockstripe clrSTRIPE_HANDLE ... (lockdev check-buffers unlockdev) .. change-state .. record io needed unlockstripe schedule io
+ *     lockstripe clrSTRIPE_HANDLE ...
+ *             (lockdev check-buffers unlockdev) ..
+ *             change-state ..
+ *             record io/ops needed unlockstripe schedule io/ops
  *  release an active stripe (release_stripe())
  *     lockdev if (!--cnt) { if  STRIPE_HANDLE, add to handle_list else add to inactive-list } unlockdev
  *
  * The refcount counts each thread that have activated the stripe,
  * plus raid5d if it is handling it, plus one for each active request
- * on a cached buffer.
+ * on a cached buffer, and plus one if the stripe is undergoing stripe
+ * operations.
+ *
+ * Stripe operations are performed outside the stripe lock,
+ * the stripe operations are:
+ * -copying data between the stripe cache and user application buffers
+ * -computing blocks to save a disk access, or to recover a missing block
+ * -updating the parity on a write operation (reconstruct write and
+ *  read-modify-write)
+ * -checking parity correctness
+ * -running i/o to disk
+ * These operations are carried out by raid5_run_ops which uses the async_tx
+ * api to (optionally) offload operations to dedicated hardware engines.
+ * When requesting an operation handle_stripe sets the pending bit for the
+ * operation and increments the count.  raid5_run_ops is then run whenever
+ * the count is non-zero.
+ * There are some critical dependencies between the operations that prevent some
+ * from being requested while another is in flight.
+ * 1/ Parity check operations destroy the in cache version of the parity block,
+ *    so we prevent parity dependent operations like writes and compute_blocks
+ *    from starting while a check is in progress.  Some dma engines can perform
+ *    the check without damaging the parity block, in these cases the parity
+ *    block is re-marked up to date (assuming the check was successful) and is
+ *    not re-read from disk.
+ * 2/ When a write operation is requested we immediately lock the affected
+ *    blocks, and mark them as not up to date.  This causes new read requests
+ *    to be held off, as well as parity checks and compute block operations.
+ * 3/ Once a compute block operation has been requested handle_stripe treats
+ *    that block as if it is up to date.  raid5_run_ops guaruntees that any
+ *    operation that is dependent on the compute block result is initiated after
+ *    the compute block completes.
  */
 
 struct stripe_head {
@@ -136,15 +169,46 @@ struct stripe_head {
        spinlock_t              lock;
        int                     bm_seq; /* sequence number for bitmap flushes */
        int                     disks;                  /* disks in stripe */
+       /* stripe_operations
+        * @pending - pending ops flags (set for request->issue->complete)
+        * @ack - submitted ops flags (set for issue->complete)
+        * @complete - completed ops flags (set for complete)
+        * @target - STRIPE_OP_COMPUTE_BLK target
+        * @count - raid5_runs_ops is set to run when this is non-zero
+        */
+       struct stripe_operations {
+               unsigned long      pending;
+               unsigned long      ack;
+               unsigned long      complete;
+               int                target;
+               int                count;
+               u32                zero_sum_result;
+       } ops;
        struct r5dev {
                struct bio      req;
                struct bio_vec  vec;
                struct page     *page;
-               struct bio      *toread, *towrite, *written;
+               struct bio      *toread, *read, *towrite, *written;
                sector_t        sector;                 /* sector of this page */
                unsigned long   flags;
        } dev[1]; /* allocated with extra space depending of RAID geometry */
 };
+
+/* stripe_head_state - collects and tracks the dynamic state of a stripe_head
+ *     for handle_stripe.  It is only valid under spin_lock(sh->lock);
+ */
+struct stripe_head_state {
+       int syncing, expanding, expanded;
+       int locked, uptodate, to_read, to_write, failed, written;
+       int to_fill, compute, req_compute, non_overwrite;
+       int failed_num;
+};
+
+/* r6_state - extra state data only relevant to r6 */
+struct r6_state {
+       int p_failed, q_failed, qd_idx, failed_num[2];
+};
+
 /* Flags */
 #define        R5_UPTODATE     0       /* page contains current data */
 #define        R5_LOCKED       1       /* IO has been submitted on "req" */
@@ -158,6 +222,15 @@ struct stripe_head {
 #define        R5_ReWrite      9       /* have tried to over-write the readerror */
 
 #define        R5_Expanded     10      /* This block now has post-expand data */
+#define        R5_Wantcompute  11 /* compute_block in progress treat as
+                                   * uptodate
+                                   */
+#define        R5_Wantfill     12 /* dev->toread contains a bio that needs
+                                   * filling
+                                   */
+#define        R5_Wantprexor   13 /* distinguish blocks ready for rmw from
+                                   * other "towrites"
+                                   */
 /*
  * Write method
  */
@@ -179,6 +252,24 @@ struct stripe_head {
 #define        STRIPE_EXPANDING        9
 #define        STRIPE_EXPAND_SOURCE    10
 #define        STRIPE_EXPAND_READY     11
+/*
+ * Operations flags (in issue order)
+ */
+#define STRIPE_OP_BIOFILL      0
+#define STRIPE_OP_COMPUTE_BLK  1
+#define STRIPE_OP_PREXOR       2
+#define STRIPE_OP_BIODRAIN     3
+#define STRIPE_OP_POSTXOR      4
+#define STRIPE_OP_CHECK        5
+#define STRIPE_OP_IO           6
+
+/* modifiers to the base operations
+ * STRIPE_OP_MOD_REPAIR_PD - compute the parity block and write it back
+ * STRIPE_OP_MOD_DMA_CHECK - parity is not corrupted by the check
+ */
+#define STRIPE_OP_MOD_REPAIR_PD 7
+#define STRIPE_OP_MOD_DMA_CHECK 8
+
 /*
  * Plugging:
  *
index f0d67cbdea40bcc7428036235ee8ce6e8ab79059..3e120587eadac53669053e040db23b747ad4a91f 100644 (file)
@@ -3,9 +3,10 @@
 
 #include <linux/raid/md.h>
 
-#define MAX_XOR_BLOCKS 5
+#define MAX_XOR_BLOCKS 4
 
-extern void xor_block(unsigned int count, unsigned int bytes, void **ptr);
+extern void xor_blocks(unsigned int count, unsigned int bytes,
+       void *dest, void **srcs);
 
 struct xor_block_template {
         struct xor_block_template *next;
index b02308ee7667790c78aed464aaddbea9e65c4fb9..3ee412bc00ecdfe12c8bfbbc4bead79fb506a938 100644 (file)
@@ -10,7 +10,7 @@
 struct screen_info {
        u8  orig_x;             /* 0x00 */
        u8  orig_y;             /* 0x01 */
-       u16 dontuse1;           /* 0x02 -- EXT_MEM_K sits here */
+       u16 ext_mem_k;          /* 0x02 */
        u16 orig_video_page;    /* 0x04 */
        u8  orig_video_mode;    /* 0x06 */
        u8  orig_video_cols;    /* 0x07 */
@@ -27,7 +27,7 @@ struct screen_info {
        u16 lfb_depth;          /* 0x16 */
        u32 lfb_base;           /* 0x18 */
        u32 lfb_size;           /* 0x1c */
-       u16 dontuse2, dontuse3; /* 0x20 -- CL_MAGIC and CL_OFFSET here */
+       u16 cl_magic, cl_offset; /* 0x20 */
        u16 lfb_linelength;     /* 0x24 */
        u8  red_size;           /* 0x26 */
        u8  red_pos;            /* 0x27 */
@@ -42,9 +42,8 @@ struct screen_info {
        u16 pages;              /* 0x32 */
        u16 vesa_attributes;    /* 0x34 */
        u32 capabilities;       /* 0x36 */
-                               /* 0x3a -- 0x3b reserved for future expansion */
-                               /* 0x3c -- 0x3f micro stack for relocatable kernels */
-};
+       u8  _reserved[6];       /* 0x3a */
+} __attribute__((packed));
 
 extern struct screen_info screen_info;
 
index 9eb9e0fe03312614b8702e0435c1604b928e4190..c11dc8aa0351e25be90e967a59d4f93b0f5e73b0 100644 (file)
@@ -71,6 +71,7 @@ struct xfrm_user_sec_ctx;
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
 
+extern unsigned long mmap_min_addr;
 /*
  * Values used in the task_security_ops calls
  */
@@ -1241,8 +1242,9 @@ struct security_operations {
        int (*file_ioctl) (struct file * file, unsigned int cmd,
                           unsigned long arg);
        int (*file_mmap) (struct file * file,
-                         unsigned long reqprot,
-                         unsigned long prot, unsigned long flags);
+                         unsigned long reqprot, unsigned long prot,
+                         unsigned long flags, unsigned long addr,
+                         unsigned long addr_only);
        int (*file_mprotect) (struct vm_area_struct * vma,
                              unsigned long reqprot,
                              unsigned long prot);
@@ -1814,9 +1816,12 @@ static inline int security_file_ioctl (struct file *file, unsigned int cmd,
 
 static inline int security_file_mmap (struct file *file, unsigned long reqprot,
                                      unsigned long prot,
-                                     unsigned long flags)
+                                     unsigned long flags,
+                                     unsigned long addr,
+                                     unsigned long addr_only)
 {
-       return security_ops->file_mmap (file, reqprot, prot, flags);
+       return security_ops->file_mmap (file, reqprot, prot, flags, addr,
+                                       addr_only);
 }
 
 static inline int security_file_mprotect (struct vm_area_struct *vma,
@@ -2489,7 +2494,9 @@ static inline int security_file_ioctl (struct file *file, unsigned int cmd,
 
 static inline int security_file_mmap (struct file *file, unsigned long reqprot,
                                      unsigned long prot,
-                                     unsigned long flags)
+                                     unsigned long flags,
+                                     unsigned long addr,
+                                     unsigned long addr_only)
 {
        return 0;
 }
index 1ebf0455e224966a1af04789391704de119d6e2b..d9377ce9ffd1739b642095a298e854dbc537718a 100644 (file)
@@ -209,5 +209,6 @@ static inline void serio_unpin_driver(struct serio *serio)
 #define SERIO_PENMOUNT 0x31
 #define SERIO_TOUCHRIGHT       0x32
 #define SERIO_TOUCHWIN 0x33
+#define SERIO_TAOSEVM  0x34
 
 #endif
index 534cdc7be58dbbef6350ddef8fd89983bb7f6e41..7a69ca3bebaf8cc33fcd1542d7a8e900774f50aa 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/sunrpc/xdr.h>
 
 #include <asm/atomic.h>
+#include <linux/rcupdate.h>
 
 /* size of the nodename buffer */
 #define UNX_MAXNODENAME        32
@@ -30,22 +31,28 @@ struct auth_cred {
 /*
  * Client user credentials
  */
+struct rpc_auth;
+struct rpc_credops;
 struct rpc_cred {
        struct hlist_node       cr_hash;        /* hash chain */
-       struct rpc_credops *    cr_ops;
-       unsigned long           cr_expire;      /* when to gc */
-       atomic_t                cr_count;       /* ref count */
-       unsigned short          cr_flags;       /* various flags */
+       struct list_head        cr_lru;         /* lru garbage collection */
+       struct rcu_head         cr_rcu;
+       struct rpc_auth *       cr_auth;
+       const struct rpc_credops *cr_ops;
 #ifdef RPC_DEBUG
        unsigned long           cr_magic;       /* 0x0f4aa4f0 */
 #endif
+       unsigned long           cr_expire;      /* when to gc */
+       unsigned long           cr_flags;       /* various flags */
+       atomic_t                cr_count;       /* ref count */
 
        uid_t                   cr_uid;
 
        /* per-flavor data */
 };
-#define RPCAUTH_CRED_NEW       0x0001
-#define RPCAUTH_CRED_UPTODATE  0x0002
+#define RPCAUTH_CRED_NEW       0
+#define RPCAUTH_CRED_UPTODATE  1
+#define RPCAUTH_CRED_HASHED    2
 
 #define RPCAUTH_CRED_MAGIC     0x0f4aa4f0
 
@@ -56,10 +63,10 @@ struct rpc_cred {
 #define RPC_CREDCACHE_MASK     (RPC_CREDCACHE_NR - 1)
 struct rpc_cred_cache {
        struct hlist_head       hashtable[RPC_CREDCACHE_NR];
-       unsigned long           nextgc;         /* next garbage collection */
-       unsigned long           expire;         /* cache expiry interval */
+       spinlock_t              lock;
 };
 
+struct rpc_authops;
 struct rpc_auth {
        unsigned int            au_cslack;      /* call cred size estimate */
                                /* guess at number of u32's auth adds before
@@ -69,7 +76,7 @@ struct rpc_auth {
        unsigned int            au_verfsize;
 
        unsigned int            au_flags;       /* various flags */
-       struct rpc_authops *    au_ops;         /* operations */
+       const struct rpc_authops *au_ops;               /* operations */
        rpc_authflavor_t        au_flavor;      /* pseudoflavor (note may
                                                 * differ from the flavor in
                                                 * au_ops->au_flavor in gss
@@ -115,17 +122,19 @@ struct rpc_credops {
                                                void *, __be32 *, void *);
 };
 
-extern struct rpc_authops      authunix_ops;
-extern struct rpc_authops      authnull_ops;
-#ifdef CONFIG_SUNRPC_SECURE
-extern struct rpc_authops      authdes_ops;
-#endif
+extern const struct rpc_authops        authunix_ops;
+extern const struct rpc_authops        authnull_ops;
+
+void __init            rpc_init_authunix(void);
+void __init            rpcauth_init_module(void);
+void __exit            rpcauth_remove_module(void);
 
-int                    rpcauth_register(struct rpc_authops *);
-int                    rpcauth_unregister(struct rpc_authops *);
+int                    rpcauth_register(const struct rpc_authops *);
+int                    rpcauth_unregister(const struct rpc_authops *);
 struct rpc_auth *      rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
-void                   rpcauth_destroy(struct rpc_auth *);
+void                   rpcauth_release(struct rpc_auth *);
 struct rpc_cred *      rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
+void                   rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
 struct rpc_cred *      rpcauth_lookupcred(struct rpc_auth *, int);
 struct rpc_cred *      rpcauth_bindcred(struct rpc_task *);
 void                   rpcauth_holdcred(struct rpc_task *);
@@ -138,8 +147,9 @@ int                 rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
 int                    rpcauth_refreshcred(struct rpc_task *);
 void                   rpcauth_invalcred(struct rpc_task *);
 int                    rpcauth_uptodatecred(struct rpc_task *);
-int                    rpcauth_init_credcache(struct rpc_auth *, unsigned long);
-void                   rpcauth_free_credcache(struct rpc_auth *);
+int                    rpcauth_init_credcache(struct rpc_auth *);
+void                   rpcauth_destroy_credcache(struct rpc_auth *);
+void                   rpcauth_clear_credcache(struct rpc_cred_cache *);
 
 static inline
 struct rpc_cred *      get_rpccred(struct rpc_cred *cred)
index 2db2fbf349472e3760a003f6d046e35687658ed6..67658e17a375194fd2e18753a7323e0ac1f2cbb6 100644 (file)
@@ -75,6 +75,7 @@ struct gss_cl_ctx {
        struct xdr_netobj       gc_wire_ctx;
        u32                     gc_win;
        unsigned long           gc_expiry;
+       struct rcu_head         gc_rcu;
 };
 
 struct gss_upcall_msg;
@@ -85,11 +86,6 @@ struct gss_cred {
        struct gss_upcall_msg   *gc_upcall;
 };
 
-#define gc_uid                 gc_base.cr_uid
-#define gc_count               gc_base.cr_count
-#define gc_flags               gc_base.cr_flags
-#define gc_expire              gc_base.cr_expire
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_AUTH_GSS_H */
 
index 66611423c8ee3763a9bcc8390d9ffab9f85cd0a7..c0d9d14983b3f191679aed01ca729838aafa7a29 100644 (file)
@@ -24,8 +24,10 @@ struct rpc_inode;
  * The high-level client handle
  */
 struct rpc_clnt {
-       atomic_t                cl_count;       /* Number of clones */
-       atomic_t                cl_users;       /* number of references */
+       struct kref             cl_kref;        /* Number of references */
+       struct list_head        cl_clients;     /* Global list of clients */
+       struct list_head        cl_tasks;       /* List of tasks */
+       spinlock_t              cl_lock;        /* spinlock */
        struct rpc_xprt *       cl_xprt;        /* transport */
        struct rpc_procinfo *   cl_procinfo;    /* procedure info */
        u32                     cl_prog,        /* RPC program number */
@@ -41,9 +43,7 @@ struct rpc_clnt {
        unsigned int            cl_softrtry : 1,/* soft timeouts */
                                cl_intr     : 1,/* interruptible */
                                cl_discrtry : 1,/* disconnect before retry */
-                               cl_autobind : 1,/* use getport() */
-                               cl_oneshot  : 1,/* dispose after use */
-                               cl_dead     : 1;/* abandoned */
+                               cl_autobind : 1;/* use getport() */
 
        struct rpc_rtt *        cl_rtt;         /* RTO estimator data */
 
@@ -98,6 +98,7 @@ struct rpc_create_args {
        int                     protocol;
        struct sockaddr         *address;
        size_t                  addrsize;
+       struct sockaddr         *saddress;
        struct rpc_timeout      *timeout;
        char                    *servername;
        struct rpc_program      *program;
@@ -110,20 +111,20 @@ struct rpc_create_args {
 #define RPC_CLNT_CREATE_HARDRTRY       (1UL << 0)
 #define RPC_CLNT_CREATE_INTR           (1UL << 1)
 #define RPC_CLNT_CREATE_AUTOBIND       (1UL << 2)
-#define RPC_CLNT_CREATE_ONESHOT                (1UL << 3)
-#define RPC_CLNT_CREATE_NONPRIVPORT    (1UL << 4)
-#define RPC_CLNT_CREATE_NOPING         (1UL << 5)
-#define RPC_CLNT_CREATE_DISCRTRY       (1UL << 6)
+#define RPC_CLNT_CREATE_NONPRIVPORT    (1UL << 3)
+#define RPC_CLNT_CREATE_NOPING         (1UL << 4)
+#define RPC_CLNT_CREATE_DISCRTRY       (1UL << 5)
 
 struct rpc_clnt *rpc_create(struct rpc_create_args *args);
 struct rpc_clnt        *rpc_bind_new_program(struct rpc_clnt *,
                                struct rpc_program *, int);
 struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
-int            rpc_shutdown_client(struct rpc_clnt *);
-int            rpc_destroy_client(struct rpc_clnt *);
+void           rpc_shutdown_client(struct rpc_clnt *);
 void           rpc_release_client(struct rpc_clnt *);
+
 int            rpcb_register(u32, u32, int, unsigned short, int *);
-void           rpcb_getport(struct rpc_task *);
+int            rpcb_getport_sync(struct sockaddr_in *, __u32, __u32, int);
+void           rpcb_getport_async(struct rpc_task *);
 
 void           rpc_call_setup(struct rpc_task *, struct rpc_message *, int);
 
@@ -132,20 +133,16 @@ int               rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg,
                               void *calldata);
 int            rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
                              int flags);
+struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
+                              int flags);
 void           rpc_restart_call(struct rpc_task *);
 void           rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
 void           rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
 void           rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
 size_t         rpc_max_payload(struct rpc_clnt *);
 void           rpc_force_rebind(struct rpc_clnt *);
-int            rpc_ping(struct rpc_clnt *clnt, int flags);
 size_t         rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);
 char *         rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t);
 
-/*
- * Helper function for NFSroot support
- */
-int            rpcb_getport_external(struct sockaddr_in *, __u32, __u32, int);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_CLNT_H */
index 5eca9e442051310525162222c9891776be778d9d..bbac101ac37278a518011a3962cb41a89222bdd3 100644 (file)
@@ -77,7 +77,7 @@ struct gss_api_mech {
        struct module           *gm_owner;
        struct xdr_netobj       gm_oid;
        char                    *gm_name;
-       struct gss_api_ops      *gm_ops;
+       const struct gss_api_ops *gm_ops;
        /* pseudoflavors supported by this mechanism: */
        int                     gm_pf_num;
        struct pf_desc *        gm_pfs;
index ad293760f6ebaa23b6d1c85666eb78e57ffc873e..51b977a4ca203eee00cb7b44f769a29c710064d5 100644 (file)
@@ -23,9 +23,11 @@ struct rpc_inode {
        void *private;
        struct list_head pipe;
        struct list_head in_upcall;
+       struct list_head in_downcall;
        int pipelen;
        int nreaders;
        int nwriters;
+       int nkern_readwriters;
        wait_queue_head_t waitq;
 #define RPC_PIPE_WAIT_FOR_OPEN 1
        int flags;
index 2047fb202a137c048264b77036b3072849d21f3c..8ea077db0099cc636a2c9053e7cd1cc17abec2a0 100644 (file)
@@ -98,7 +98,6 @@ struct rpc_task {
        unsigned short          tk_pid;         /* debugging aid */
 #endif
 };
-#define tk_auth                        tk_client->cl_auth
 #define tk_xprt                        tk_client->cl_xprt
 
 /* support walking a list of tasks on a wait queue */
@@ -110,11 +109,6 @@ struct rpc_task {
        if (!list_empty(head) &&  \
            ((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1))
 
-/* .. and walking list of all tasks */
-#define        alltask_for_each(task, pos, head) \
-       list_for_each(pos, head) \
-               if ((task=list_entry(pos, struct rpc_task, tk_task)),1)
-
 typedef void                   (*rpc_action)(struct rpc_task *);
 
 struct rpc_call_ops {
index e21dd93ac4b7c3a197f8b1d843d2afbddadc8ff0..a53e0fa855d2e26f9b2827f616a7f0f9964b00eb 100644 (file)
@@ -59,6 +59,7 @@ struct svc_sock {
        /* cache of various info for TCP sockets */
        void                    *sk_info_authunix;
 
+       struct sockaddr_storage sk_local;       /* local address */
        struct sockaddr_storage sk_remote;      /* remote peer's address */
        int                     sk_remotelen;   /* length of address */
 };
index 34f7590506fac8239add141704e2c59b83878c9d..d11cedd14f0f59a9e267b97beddbde1ae13aca74 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/msg_prot.h>
 
+#ifdef __KERNEL__
+
 extern unsigned int xprt_udp_slot_table_entries;
 extern unsigned int xprt_tcp_slot_table_entries;
 
@@ -194,7 +196,13 @@ struct rpc_xprt {
        char *                  address_strings[RPC_DISPLAY_MAX];
 };
 
-#ifdef __KERNEL__
+struct rpc_xprtsock_create {
+       int                     proto;          /* IPPROTO_UDP or IPPROTO_TCP */
+       struct sockaddr *       srcaddr;        /* optional local address */
+       struct sockaddr *       dstaddr;        /* remote peer address */
+       size_t                  addrlen;
+       struct rpc_timeout *    timeout;        /* optional timeout parameters */
+};
 
 /*
  * Transport operations used by ULPs
@@ -204,7 +212,7 @@ void                        xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long
 /*
  * Generic internal transport functions
  */
-struct rpc_xprt *      xprt_create_transport(int proto, struct sockaddr *addr, size_t size, struct rpc_timeout *toparms);
+struct rpc_xprt *      xprt_create_transport(struct rpc_xprtsock_create *args);
 void                   xprt_connect(struct rpc_task *task);
 void                   xprt_reserve(struct rpc_task *task);
 int                    xprt_reserve_xprt(struct rpc_task *task);
@@ -242,8 +250,8 @@ void                        xprt_disconnect(struct rpc_xprt *xprt);
 /*
  * Socket transport setup operations
  */
-struct rpc_xprt *      xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to);
-struct rpc_xprt *      xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to);
+struct rpc_xprt *      xs_setup_udp(struct rpc_xprtsock_create *args);
+struct rpc_xprt *      xs_setup_tcp(struct rpc_xprtsock_create *args);
 int                    init_socket_xprt(void);
 void                   cleanup_socket_xprt(void);
 
index e699ab279c2c1302d03bdb25e10bd36567fbc507..e285746588d68baf4dccc894e70768005342e04a 100644 (file)
@@ -101,8 +101,7 @@ struct sysdev_attribute {
 
 #define _SYSDEV_ATTR(_name,_mode,_show,_store)                 \
 {                                                              \
-       .attr = { .name = __stringify(_name), .mode = _mode,    \
-                .owner = THIS_MODULE },                        \
+       .attr = { .name = __stringify(_name), .mode = _mode },  \
        .show   = _show,                                        \
        .store  = _store,                                       \
 }
index 7d5d1ec95c2e4b8dc719c042cc6a178550be3f09..be8228e50a2750398f19d9f1699d84e7575cad91 100644 (file)
@@ -19,10 +19,15 @@ struct kobject;
 struct module;
 struct nameidata;
 struct dentry;
+struct sysfs_dirent;
 
+/* FIXME
+ * The *owner field is no longer used, but leave around
+ * until the tree gets cleaned up fully.
+ */
 struct attribute {
        const char              * name;
-       struct module           * owner;
+       struct module           * owner;
        mode_t                  mode;
 };
 
@@ -39,14 +44,14 @@ struct attribute_group {
  */
 
 #define __ATTR(_name,_mode,_show,_store) { \
-       .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
+       .attr = {.name = __stringify(_name), .mode = _mode },   \
        .show   = _show,                                        \
        .store  = _store,                                       \
 }
 
 #define __ATTR_RO(_name) { \
-       .attr   = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE },   \
-       .show   = _name##_show, \
+       .attr   = { .name = __stringify(_name), .mode = 0444 }, \
+       .show   = _name##_show,                                 \
 }
 
 #define __ATTR_NULL { .attr = { .name = NULL } }
@@ -59,8 +64,10 @@ struct bin_attribute {
        struct attribute        attr;
        size_t                  size;
        void                    *private;
-       ssize_t (*read)(struct kobject *, char *, loff_t, size_t);
-       ssize_t (*write)(struct kobject *, char *, loff_t, size_t);
+       ssize_t (*read)(struct kobject *, struct bin_attribute *,
+                       char *, loff_t, size_t);
+       ssize_t (*write)(struct kobject *, struct bin_attribute *,
+                        char *, loff_t, size_t);
        int (*mmap)(struct kobject *, struct bin_attribute *attr,
                    struct vm_area_struct *vma);
 };
@@ -70,12 +77,16 @@ struct sysfs_ops {
        ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
 };
 
+#define SYSFS_TYPE_MASK                0x00ff
 #define SYSFS_ROOT             0x0001
 #define SYSFS_DIR              0x0002
 #define SYSFS_KOBJ_ATTR        0x0004
 #define SYSFS_KOBJ_BIN_ATTR    0x0008
 #define SYSFS_KOBJ_LINK        0x0020
-#define SYSFS_NOT_PINNED       (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK)
+#define SYSFS_COPY_NAME                (SYSFS_DIR | SYSFS_KOBJ_LINK)
+
+#define SYSFS_FLAG_MASK                ~SYSFS_TYPE_MASK
+#define SYSFS_FLAG_REMOVED     0x0100
 
 #ifdef CONFIG_SYSFS
 
@@ -83,13 +94,14 @@ extern int sysfs_schedule_callback(struct kobject *kobj,
                void (*func)(void *), void *data, struct module *owner);
 
 extern int __must_check
-sysfs_create_dir(struct kobject *, struct dentry *);
+sysfs_create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent_sd);
 
 extern void
 sysfs_remove_dir(struct kobject *);
 
 extern int __must_check
-sysfs_rename_dir(struct kobject *, struct dentry *, const char *new_name);
+sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd,
+                const char *new_name);
 
 extern int __must_check
 sysfs_move_dir(struct kobject *, struct kobject *);
@@ -129,8 +141,8 @@ void sysfs_notify(struct kobject * k, char *dir, char *attr);
 
 extern int sysfs_make_shadowed_dir(struct kobject *kobj,
        void * (*follow_link)(struct dentry *, struct nameidata *));
-extern struct dentry *sysfs_create_shadow_dir(struct kobject *kobj);
-extern void sysfs_remove_shadow_dir(struct dentry *dir);
+extern struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj);
+extern void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd);
 
 extern int __must_check sysfs_init(void);
 
@@ -142,7 +154,8 @@ static inline int sysfs_schedule_callback(struct kobject *kobj,
        return -ENOSYS;
 }
 
-static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow)
+static inline int sysfs_create_dir(struct kobject *kobj,
+                                  struct sysfs_dirent *shadow_parent_sd)
 {
        return 0;
 }
@@ -152,9 +165,9 @@ static inline void sysfs_remove_dir(struct kobject * k)
        ;
 }
 
-static inline int sysfs_rename_dir(struct kobject * k,
-                                       struct dentry *new_parent,
-                                       const char *new_name)
+static inline int sysfs_rename_dir(struct kobject *kobj,
+                                  struct sysfs_dirent *new_parent_sd,
+                                  const char *new_name)
 {
        return 0;
 }
index da6c39b2d051c30c7ec14df2b8f3b27115569ddc..d0890a7e5babb1f96b78a04fa6f471df0edbdd8e 100644 (file)
        for_each_online_node(node)                                              \
                if (nr_cpus_node(node))
 
-#ifndef node_distance
 /* Conform to ACPI 2.0 SLIT distance definitions */
 #define LOCAL_DISTANCE         10
 #define REMOTE_DISTANCE                20
+#ifndef node_distance
 #define node_distance(from,to) ((from) == (to) ? LOCAL_DISTANCE : REMOTE_DISTANCE)
 #endif
 #ifndef RECLAIM_DISTANCE
index 56aa2ee21f1b284659e6164bcc9f2dea59ada2c1..7a60946df3b675889f4e4bdc2e5b77ab7fe45a38 100644 (file)
@@ -146,6 +146,10 @@ struct usb_interface {
                                         * active alternate setting */
        unsigned num_altsetting;        /* number of alternate settings */
 
+       /* If there is an interface association descriptor then it will list
+        * the associated interfaces */
+       struct usb_interface_assoc_descriptor *intf_assoc;
+
        int minor;                      /* minor number this interface is
                                         * bound to */
        enum usb_interface_condition condition;         /* state of binding */
@@ -175,6 +179,7 @@ void usb_put_intf(struct usb_interface *intf);
 
 /* this maximum is arbitrary */
 #define USB_MAXINTERFACES      32
+#define USB_MAXIADS            USB_MAXINTERFACES/2
 
 /**
  * struct usb_interface_cache - long-term representation of a device interface
@@ -245,6 +250,11 @@ struct usb_host_config {
        struct usb_config_descriptor    desc;
 
        char *string;           /* iConfiguration string, if present */
+
+       /* List of any Interface Association Descriptors in this
+        * configuration. */
+       struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];
+
        /* the interfaces associated with this configuration,
         * stored in no particular order */
        struct usb_interface *interface[USB_MAXINTERFACES];
@@ -403,6 +413,8 @@ struct usb_device {
 
        unsigned auto_pm:1;             /* autosuspend/resume in progress */
        unsigned do_remote_wakeup:1;    /* remote wakeup should be enabled */
+       unsigned reset_resume:1;        /* needs reset instead of resume */
+       unsigned persist_enabled:1;     /* USB_PERSIST enabled for this dev */
        unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
        unsigned autoresume_disabled:1;  /*  disabled by the user */
 #endif
@@ -770,6 +782,28 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor
        .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
        .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
 
+/**
+ * USB_DEVICE_AND_INTERFACE_INFO - macro used to describe a specific usb device
+ *             with a class of usb interfaces
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ * @cl: bInterfaceClass value
+ * @sc: bInterfaceSubClass value
+ * @pr: bInterfaceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific device with a specific class of interfaces.
+ *
+ * This is especially useful when explicitly matching devices that have
+ * vendor specific bDeviceClass values, but standards-compliant interfaces.
+ */
+#define USB_DEVICE_AND_INTERFACE_INFO(vend,prod,cl,sc,pr) \
+       .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
+               | USB_DEVICE_ID_MATCH_DEVICE, \
+       .idVendor = (vend), .idProduct = (prod), \
+       .bInterfaceClass = (cl), \
+       .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
+
 /* ----------------------------------------------------------------------- */
 
 /* Stuff for dynamic usb ids */
@@ -816,10 +850,15 @@ struct usbdrv_wrap {
  *     do (or don't) show up otherwise in the filesystem.
  * @suspend: Called when the device is going to be suspended by the system.
  * @resume: Called when the device is being resumed by the system.
+ * @reset_resume: Called when the suspended device has been reset instead
+ *     of being resumed.
  * @pre_reset: Called by usb_reset_composite_device() when the device
  *     is about to be reset.
  * @post_reset: Called by usb_reset_composite_device() after the device
- *     has been reset.
+ *     has been reset, or in lieu of @resume following a reset-resume
+ *     (i.e., the device is reset instead of being resumed, as might
+ *     happen if power was lost).  The second argument tells which is
+ *     the reason.
  * @id_table: USB drivers use ID table to support hotplugging.
  *     Export this with MODULE_DEVICE_TABLE(usb,...).  This must be set
  *     or your driver's probe function will never get called.
@@ -859,9 +898,10 @@ struct usb_driver {
 
        int (*suspend) (struct usb_interface *intf, pm_message_t message);
        int (*resume) (struct usb_interface *intf);
+       int (*reset_resume)(struct usb_interface *intf);
 
-       void (*pre_reset) (struct usb_interface *intf);
-       void (*post_reset) (struct usb_interface *intf);
+       int (*pre_reset)(struct usb_interface *intf);
+       int (*post_reset)(struct usb_interface *intf);
 
        const struct usb_device_id *id_table;
 
@@ -964,6 +1004,7 @@ extern int usb_disabled(void);
 #define URB_ZERO_PACKET                0x0040  /* Finish bulk OUT with short packet */
 #define URB_NO_INTERRUPT       0x0080  /* HINT: no non-error interrupt
                                         * needed */
+#define URB_FREE_BUFFER                0x0100  /* Free transfer buffer with the URB */
 
 struct usb_iso_packet_descriptor {
        unsigned int offset;
@@ -974,11 +1015,26 @@ struct usb_iso_packet_descriptor {
 
 struct urb;
 
+struct usb_anchor {
+       struct list_head urb_list;
+       wait_queue_head_t wait;
+       spinlock_t lock;
+};
+
+static inline void init_usb_anchor(struct usb_anchor *anchor)
+{
+       INIT_LIST_HEAD(&anchor->urb_list);
+       init_waitqueue_head(&anchor->wait);
+       spin_lock_init(&anchor->lock);
+}
+
 typedef void (*usb_complete_t)(struct urb *);
 
 /**
  * struct urb - USB Request Block
  * @urb_list: For use by current owner of the URB.
+ * @anchor_list: membership in the list of an anchor
+ * @anchor: to anchor URBs to a common mooring
  * @pipe: Holds endpoint number, direction, type, and more.
  *     Create these values with the eight macros available;
  *     usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl"
@@ -1151,6 +1207,8 @@ struct urb
        /* public: documented fields in the urb that can be used by drivers */
        struct list_head urb_list;      /* list head for use by the urb's
                                         * current owner */
+       struct list_head anchor_list;   /* the URB may be anchored by the driver */
+       struct usb_anchor *anchor;
        struct usb_device *dev;         /* (in) pointer to associated device */
        unsigned int pipe;              /* (in) pipe information */
        int status;                     /* (return) non-ISO status */
@@ -1286,6 +1344,11 @@ extern struct urb *usb_get_urb(struct urb *urb);
 extern int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
 extern int usb_unlink_urb(struct urb *urb);
 extern void usb_kill_urb(struct urb *urb);
+extern void usb_kill_anchored_urbs(struct usb_anchor *anchor);
+extern void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor);
+extern void usb_unanchor_urb(struct urb *urb);
+extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
+                                        unsigned int timeout);
 
 void *usb_buffer_alloc (struct usb_device *dev, size_t size,
        gfp_t mem_flags, dma_addr_t *dma);
index 43f160cfe00342af04b57183070b6315a31d87c8..6ce42bf9f743960a97fe95317542d042046dc059 100644 (file)
@@ -1,5 +1,6 @@
 unifdef-y += audio.h
 unifdef-y += cdc.h
 unifdef-y += ch9.h
+unifdef-y += gadgetfs.h
 unifdef-y += midi.h
 
similarity index 74%
rename from include/linux/usb_gadgetfs.h
rename to include/linux/usb/gadgetfs.h
index 8086d5a9b94e582b595fb32df5afbb2e5a391fb5..e8654c338729438de4b6d887b53c7dec725b3600 100644 (file)
@@ -1,3 +1,5 @@
+#ifndef __LINUX_USB_GADGETFS_H
+#define __LINUX_USB_GADGETFS_H
 
 #include <asm/types.h>
 #include <asm/ioctl.h>
@@ -7,11 +9,12 @@
 /*
  * Filesystem based user-mode API to USB Gadget controller hardware
  *
- * Almost everything can be done with only read and write operations,
+ * Other than ep0 operations, most things are done by read() and write()
  * on endpoint files found in one directory.  They are configured by
  * writing descriptors, and then may be used for normal stream style
  * i/o requests.  When ep0 is configured, the device can enumerate;
- * when it's closed, the device disconnects from usb.
+ * when it's closed, the device disconnects from usb.  Operations on
+ * ep0 require ioctl() operations.
  *
  * Configuration and device descriptors get written to /dev/gadget/$CHIP,
  * which may then be used to read usb_gadgetfs_event structs.  The driver
@@ -21,9 +24,9 @@
  */
 
 /*
- * Events are delivered on the ep0 file descriptor, if the user mode driver
+ * Events are delivered on the ep0 file descriptor, when the user mode driver
  * reads from this file descriptor after writing the descriptors.  Don't
- * stop polling this descriptor, if you write that kind of driver.
+ * stop polling this descriptor.
  */
 
 enum usb_gadgetfs_event_type {
@@ -36,8 +39,10 @@ enum usb_gadgetfs_event_type {
        // and likely more !
 };
 
+/* NOTE:  this structure must stay the same size and layout on
+ * both 32-bit and 64-bit kernels.
+ */
 struct usb_gadgetfs_event {
-       enum usb_gadgetfs_event_type    type;
        union {
                // NOP, DISCONNECT, SUSPEND: nothing
                // ... some hardware can't report disconnection
@@ -46,19 +51,20 @@ struct usb_gadgetfs_event {
                enum usb_device_speed   speed;
 
                // SETUP: packet; DATA phase i/o precedes next event
-               // (setup.bmRequestType & USB_DIR_IN) flags direction 
+               // (setup.bmRequestType & USB_DIR_IN) flags direction
                // ... includes SET_CONFIGURATION, SET_INTERFACE
                struct usb_ctrlrequest  setup;
        } u;
+       enum usb_gadgetfs_event_type    type;
 };
 
 
 /* endpoint ioctls */
 
 /* IN transfers may be reported to the gadget driver as complete
- *     when the fifo is loaded, before the host reads the data;
+ *     when the fifo is loaded, before the host reads the data;
  * OUT transfers may be reported to the host's "client" driver as
- *     complete when they're sitting in the FIFO unread.
+ *     complete when they're sitting in the FIFO unread.
  * THIS returns how many bytes are "unclaimed" in the endpoint fifo
  * (needed for precise fault handling, when the hardware allows it)
  */
@@ -72,4 +78,4 @@ struct usb_gadgetfs_event {
  */
 #define        GADGETFS_CLEAR_HALT     _IO('g',3)
 
-
+#endif /* __LINUX_USB_GADGETFS_H */
index 6bac8faacbc6e8f00de074e62735f801a8213686..8da374caf582aeb3136c5d3f90722906ca8fa2dd 100644 (file)
@@ -9,3 +9,6 @@
 
 /* string descriptors must not be fetched using a 255-byte read */
 #define USB_QUIRK_STRING_FETCH_255     0x00000002
+
+/* device can't resume correctly so reset it instead */
+#define USB_QUIRK_RESET_RESUME         0x00000004
index 32acbae28d24d34a1ea9d011945e7cc5e9e3ee06..e8b8928232c85ca2db65b12b997acc4832dbb55e 100644 (file)
@@ -221,6 +221,9 @@ struct usb_serial_driver {
        int (*port_probe) (struct usb_serial_port *port);
        int (*port_remove) (struct usb_serial_port *port);
 
+       int (*suspend) (struct usb_serial *serial, pm_message_t message);
+       int (*resume) (struct usb_serial *serial);
+
        /* serial function calls */
        int  (*open)            (struct usb_serial_port *port, struct file * filp);
        void (*close)           (struct usb_serial_port *port, struct file * filp);
@@ -249,6 +252,9 @@ extern void usb_serial_port_softint(struct usb_serial_port *port);
 extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
 extern void usb_serial_disconnect(struct usb_interface *iface);
 
+extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message);
+extern int usb_serial_resume(struct usb_interface *intf);
+
 extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest);
 extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit);
 
@@ -269,6 +275,7 @@ extern void usb_serial_put(struct usb_serial *serial);
 extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
 extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count);
 extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
+extern int usb_serial_generic_resume (struct usb_serial *serial);
 extern int usb_serial_generic_write_room (struct usb_serial_port *port);
 extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
 extern void usb_serial_generic_read_bulk_callback (struct urb *urb);
index e17186dbcdcabfbcbe32a02917e46c9eea270ac3..4f59b2aa8a9e002caf7a343735de86fd518d28ee 100644 (file)
@@ -110,13 +110,6 @@ struct usb_ep_ops {
                gfp_t gfp_flags);
        void (*free_request) (struct usb_ep *ep, struct usb_request *req);
 
-       void *(*alloc_buffer) (struct usb_ep *ep, unsigned bytes,
-               dma_addr_t *dma, gfp_t gfp_flags);
-       void (*free_buffer) (struct usb_ep *ep, void *buf, dma_addr_t dma,
-               unsigned bytes);
-       // NOTE:  on 2.6, drivers may also use dma_map() and
-       // dma_sync_single_*() to directly manage dma overhead. 
-
        int (*queue) (struct usb_ep *ep, struct usb_request *req,
                gfp_t gfp_flags);
        int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
@@ -234,47 +227,6 @@ usb_ep_free_request (struct usb_ep *ep, struct usb_request *req)
        ep->ops->free_request (ep, req);
 }
 
-/**
- * usb_ep_alloc_buffer - allocate an I/O buffer
- * @ep:the endpoint associated with the buffer
- * @len:length of the desired buffer
- * @dma:pointer to the buffer's DMA address; must be valid
- * @gfp_flags:GFP_* flags to use
- *
- * Returns a new buffer, or null if one could not be allocated.
- * The buffer is suitably aligned for dma, if that endpoint uses DMA,
- * and the caller won't have to care about dma-inconsistency
- * or any hidden "bounce buffer" mechanism.  No additional per-request
- * DMA mapping will be required for such buffers.
- * Free it later with usb_ep_free_buffer().
- *
- * You don't need to use this call to allocate I/O buffers unless you
- * want to make sure drivers don't incur costs for such "bounce buffer"
- * copies or per-request DMA mappings.
- */
-static inline void *
-usb_ep_alloc_buffer (struct usb_ep *ep, unsigned len, dma_addr_t *dma,
-       gfp_t gfp_flags)
-{
-       return ep->ops->alloc_buffer (ep, len, dma, gfp_flags);
-}
-
-/**
- * usb_ep_free_buffer - frees an i/o buffer
- * @ep:the endpoint associated with the buffer
- * @buf:CPU view address of the buffer
- * @dma:the buffer's DMA address
- * @len:length of the buffer
- *
- * reverses the effect of usb_ep_alloc_buffer().
- * caller guarantees the buffer will no longer be accessed
- */
-static inline void
-usb_ep_free_buffer (struct usb_ep *ep, void *buf, dma_addr_t dma, unsigned len)
-{
-       ep->ops->free_buffer (ep, buf, dma, len);
-}
-
 /**
  * usb_ep_queue - queues (submits) an I/O request to an endpoint.
  * @ep:the endpoint associated with the request
index 5c070176d9ab30bb1bdc8b5ae7524322070b70fe..12243e80c70615676b224310ed90d1785128662b 100644 (file)
@@ -385,7 +385,6 @@ struct ib_cm_rep_param {
        u8              private_data_len;
        u8              responder_resources;
        u8              initiator_depth;
-       u8              target_ack_delay;
        u8              failover_accepted;
        u8              flow_control;
        u8              rnr_retry_count;
index 739fa4d0e539bc195a1dc02494c3def9eff352e6..30712ddd8a5e6b6cc1add751f95948e9a3382bbd 100644 (file)
 #define IB_QP1_QKEY    0x80010000
 #define IB_QP_SET_QKEY 0x80000000
 
+#define IB_DEFAULT_PKEY_PARTIAL 0x7FFF
+#define IB_DEFAULT_PKEY_FULL   0xFFFF
+
 enum {
        IB_MGMT_MAD_HDR = 24,
        IB_MGMT_MAD_DATA = 232,
index 9bd93de01f4a95ab6abb0729401bf424cf5fab21..015d60cfd90e4f67f07380fac6c05d44aec81580 100644 (file)
@@ -488,8 +488,7 @@ static void free_modinfo_##field(struct module *mod)                  \
         mod->field = NULL;                                            \
 }                                                                     \
 static struct module_attribute modinfo_##field = {                    \
-       .attr = { .name = __stringify(field), .mode = 0444,           \
-                 .owner = THIS_MODULE },                             \
+       .attr = { .name = __stringify(field), .mode = 0444 },         \
        .show = show_modinfo_##field,                                 \
        .setup = setup_modinfo_##field,                               \
        .test = modinfo_##field##_exists,                             \
@@ -793,7 +792,7 @@ static ssize_t show_refcnt(struct module_attribute *mattr,
 }
 
 static struct module_attribute refcnt = {
-       .attr = { .name = "refcnt", .mode = 0444, .owner = THIS_MODULE },
+       .attr = { .name = "refcnt", .mode = 0444 },
        .show = show_refcnt,
 };
 
@@ -851,7 +850,7 @@ static ssize_t show_initstate(struct module_attribute *mattr,
 }
 
 static struct module_attribute initstate = {
-       .attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE },
+       .attr = { .name = "initstate", .mode = 0444 },
        .show = show_initstate,
 };
 
@@ -1032,7 +1031,6 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,
                sattr->mattr.show = module_sect_show;
                sattr->mattr.store = NULL;
                sattr->mattr.attr.name = sattr->name;
-               sattr->mattr.attr.owner = mod;
                sattr->mattr.attr.mode = S_IRUGO;
                *(gattr++) = &(sattr++)->mattr.attr;
        }
@@ -1090,7 +1088,6 @@ int module_add_modinfo_attrs(struct module *mod)
                if (!attr->test ||
                    (attr->test && attr->test(mod))) {
                        memcpy(temp_attr, attr, sizeof(*temp_attr));
-                       temp_attr->attr.owner = mod;
                        error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);
                        ++temp_attr;
                }
index e61c46c97ce72ec1fb9615783e02dd4afb7c9990..effbaaedd7f328ac8a69bc246e60903b5babd271 100644 (file)
@@ -491,7 +491,6 @@ param_sysfs_setup(struct module_kobject *mk,
                        pattr->mattr.show = param_attr_show;
                        pattr->mattr.store = param_attr_store;
                        pattr->mattr.attr.name = (char *)&kp->name[name_skip];
-                       pattr->mattr.attr.owner = mk->mod;
                        pattr->mattr.attr.mode = kp->perm;
                        *(gattr++) = &(pattr++)->mattr.attr;
                }
index 3b299fb3855cc5384fb520beb18b6f6a904da511..a615a8f513fc890eaa1a11a34ae5e08c78895bba 100644 (file)
@@ -1061,7 +1061,7 @@ static struct pipe_buf_operations relay_pipe_buf_ops = {
        .get = generic_pipe_buf_get,
 };
 
-/**
+/*
  *     subbuf_splice_actor - splice up to one subbuf's worth of data
  */
 static int subbuf_splice_actor(struct file *in,
@@ -1074,7 +1074,9 @@ static int subbuf_splice_actor(struct file *in,
        unsigned int pidx, poff, total_len, subbuf_pages, ret;
        struct rchan_buf *rbuf = in->private_data;
        unsigned int subbuf_size = rbuf->chan->subbuf_size;
-       size_t read_start = ((size_t)*ppos) % rbuf->chan->alloc_size;
+       uint64_t pos = (uint64_t) *ppos;
+       uint32_t alloc_size = (uint32_t) rbuf->chan->alloc_size;
+       size_t read_start = (size_t) do_div(pos, alloc_size);
        size_t read_subbuf = read_start / subbuf_size;
        size_t padding = rbuf->padding[read_subbuf];
        size_t nonpad_end = read_subbuf * subbuf_size + subbuf_size - padding;
index 9fbced64bfee004e1275088bb22eb4ac848e1733..3332bbb5d5cf96d3677cbd5c20737c77a45bdf7f 100644 (file)
@@ -750,8 +750,8 @@ static const u32 prio_to_wmult[40] = {
        48356,   60446,   75558,   94446,  118058,  147573,
        184467,  230589,  288233,  360285,  450347,
        562979,  703746,  879575, 1099582, 1374389,
-       717986, 2147483, 2684354, 3355443, 4194304,
-       244160, 6557201, 8196502, 10250518, 12782640,
+       1717986, 2147483, 2684354, 3355443, 4194304,
+       5244160, 6557201, 8196502, 10250518, 12782640,
        16025997, 19976592, 24970740, 31350126, 39045157,
        49367440, 61356675, 76695844, 95443717, 119304647,
        148102320, 186737708, 238609294, 286331153,
@@ -4647,14 +4647,14 @@ static void show_task(struct task_struct *p)
        state = p->state ? __ffs(p->state) + 1 : 0;
        printk("%-13.13s %c", p->comm,
                state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?');
-#if (BITS_PER_LONG == 32)
+#if BITS_PER_LONG == 32
        if (state == TASK_RUNNING)
-               printk(" running ");
+               printk(" running  ");
        else
-               printk(" %08lX ", thread_saved_pc(p));
+               printk(" %08lx ", thread_saved_pc(p));
 #else
        if (state == TASK_RUNNING)
-               printk("  running task   ");
+               printk("  running task    ");
        else
                printk(" %016lx ", thread_saved_pc(p));
 #endif
@@ -4666,11 +4666,7 @@ static void show_task(struct task_struct *p)
                free = (unsigned long)n - (unsigned long)end_of_stack(p);
        }
 #endif
-       printk("%5lu %5d %6d", free, p->pid, p->parent->pid);
-       if (!p->mm)
-               printk(" (L-TLB)\n");
-       else
-               printk(" (NOTLB)\n");
+       printk("%5lu %5d %6d\n", free, p->pid, p->parent->pid);
 
        if (state != TASK_RUNNING)
                show_stack(p, NULL);
@@ -4680,14 +4676,12 @@ void show_state_filter(unsigned long state_filter)
 {
        struct task_struct *g, *p;
 
-#if (BITS_PER_LONG == 32)
-       printk("\n"
-              "                         free                        sibling\n");
-       printk("  task             PC    stack   pid father child younger older\n");
+#if BITS_PER_LONG == 32
+       printk(KERN_INFO
+               "  task                PC stack   pid father\n");
 #else
-       printk("\n"
-              "                                 free                        sibling\n");
-       printk("  task                 PC        stack   pid father child younger older\n");
+       printk(KERN_INFO
+               "  task                        PC stack   pid father\n");
 #endif
        read_lock(&tasklist_lock);
        do_each_thread(g, p) {
@@ -4778,7 +4772,7 @@ cpumask_t nohz_cpu_mask = CPU_MASK_NONE;
 static inline void sched_init_granularity(void)
 {
        unsigned int factor = 1 + ilog2(num_online_cpus());
-       const unsigned long gran_limit = 10000000;
+       const unsigned long gran_limit = 100000000;
 
        sysctl_sched_granularity *= factor;
        if (sysctl_sched_granularity > gran_limit)
index 1baf87cceb7c0a2d93151aa0b03e71de9c088d5d..29f2c21e7da231eec8418575e634815b39330f83 100644 (file)
@@ -171,7 +171,7 @@ static int sched_debug_show(struct seq_file *m, void *v)
        u64 now = ktime_to_ns(ktime_get());
        int cpu;
 
-       SEQ_printf(m, "Sched Debug Version: v0.04, cfs-v20, %s %.*s\n",
+       SEQ_printf(m, "Sched Debug Version: v0.05, %s %.*s\n",
                init_utsname()->release,
                (int)strcspn(init_utsname()->version, " "),
                init_utsname()->version);
index 51f5dac42a00c9f56943a44b7d1865f604d84bde..d93e13d93f24c0c25d0bfc9cfe4944cd239fc10f 100644 (file)
@@ -949,6 +949,16 @@ static ctl_table vm_table[] = {
                .strategy       = &sysctl_jiffies,
        },
 #endif
+#ifdef CONFIG_SECURITY
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "mmap_min_addr",
+               .data           = &mmap_min_addr,
+               .maxlen         = sizeof(unsigned long),
+               .mode           = 0644,
+               .proc_handler   = &proc_doulongvec_minmax,
+       },
+#endif
 #if defined(CONFIG_X86_32) || \
    (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
        {
index 305117ca2d415a1adf91700fe34a06d88028de67..b98f01a2eb946b221f5d7d7d193422f95e607a3a 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -70,6 +70,26 @@ static void free_layer(struct idr *idp, struct idr_layer *p)
        spin_unlock_irqrestore(&idp->lock, flags);
 }
 
+static void idr_mark_full(struct idr_layer **pa, int id)
+{
+       struct idr_layer *p = pa[0];
+       int l = 0;
+
+       __set_bit(id & IDR_MASK, &p->bitmap);
+       /*
+        * If this layer is full mark the bit in the layer above to
+        * show that this part of the radix tree is full.  This may
+        * complete the layer above and require walking up the radix
+        * tree.
+        */
+       while (p->bitmap == IDR_FULL) {
+               if (!(p = pa[++l]))
+                       break;
+               id = id >> IDR_BITS;
+               __set_bit((id & IDR_MASK), &p->bitmap);
+       }
+}
+
 /**
  * idr_pre_get - reserver resources for idr allocation
  * @idp:       idr handle
@@ -95,15 +115,15 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
 }
 EXPORT_SYMBOL(idr_pre_get);
 
-static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
+static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
 {
        int n, m, sh;
        struct idr_layer *p, *new;
-       struct idr_layer *pa[MAX_LEVEL];
-       int l, id;
+       int l, id, oid;
        long bm;
 
        id = *starting_id;
+ restart:
        p = idp->top;
        l = idp->layers;
        pa[l--] = NULL;
@@ -117,12 +137,23 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
                if (m == IDR_SIZE) {
                        /* no space available go back to previous layer. */
                        l++;
+                       oid = id;
                        id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;
+
+                       /* if already at the top layer, we need to grow */
                        if (!(p = pa[l])) {
                                *starting_id = id;
                                return -2;
                        }
-                       continue;
+
+                       /* If we need to go up one layer, continue the
+                        * loop; otherwise, restart from the top.
+                        */
+                       sh = IDR_BITS * (l + 1);
+                       if (oid >> sh == id >> sh)
+                               continue;
+                       else
+                               goto restart;
                }
                if (m != n) {
                        sh = IDR_BITS*l;
@@ -144,30 +175,13 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
                pa[l--] = p;
                p = p->ary[m];
        }
-       /*
-        * We have reached the leaf node, plant the
-        * users pointer and return the raw id.
-        */
-       p->ary[m] = (struct idr_layer *)ptr;
-       __set_bit(m, &p->bitmap);
-       p->count++;
-       /*
-        * If this layer is full mark the bit in the layer above
-        * to show that this part of the radix tree is full.
-        * This may complete the layer above and require walking
-        * up the radix tree.
-        */
-       n = id;
-       while (p->bitmap == IDR_FULL) {
-               if (!(p = pa[++l]))
-                       break;
-               n = n >> IDR_BITS;
-               __set_bit((n & IDR_MASK), &p->bitmap);
-       }
-       return(id);
+
+       pa[l] = p;
+       return id;
 }
 
-static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
+static int idr_get_empty_slot(struct idr *idp, int starting_id,
+                             struct idr_layer **pa)
 {
        struct idr_layer *p, *new;
        int layers, v, id;
@@ -213,12 +227,31 @@ build_up:
        }
        idp->top = p;
        idp->layers = layers;
-       v = sub_alloc(idp, ptr, &id);
+       v = sub_alloc(idp, &id, pa);
        if (v == -2)
                goto build_up;
        return(v);
 }
 
+static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
+{
+       struct idr_layer *pa[MAX_LEVEL];
+       int id;
+
+       id = idr_get_empty_slot(idp, starting_id, pa);
+       if (id >= 0) {
+               /*
+                * Successfully found an empty slot.  Install the user
+                * pointer and mark the slot full.
+                */
+               pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr;
+               pa[0]->count++;
+               idr_mark_full(pa, id);
+       }
+
+       return id;
+}
+
 /**
  * idr_get_new_above - allocate new idr entry above or equal to a start id
  * @idp: idr handle
@@ -473,3 +506,248 @@ void idr_init(struct idr *idp)
        spin_lock_init(&idp->lock);
 }
 EXPORT_SYMBOL(idr_init);
+
+
+/*
+ * IDA - IDR based ID allocator
+ *
+ * this is id allocator without id -> pointer translation.  Memory
+ * usage is much lower than full blown idr because each id only
+ * occupies a bit.  ida uses a custom leaf node which contains
+ * IDA_BITMAP_BITS slots.
+ *
+ * 2007-04-25  written by Tejun Heo <htejun@gmail.com>
+ */
+
+static void free_bitmap(struct ida *ida, struct ida_bitmap *bitmap)
+{
+       unsigned long flags;
+
+       if (!ida->free_bitmap) {
+               spin_lock_irqsave(&ida->idr.lock, flags);
+               if (!ida->free_bitmap) {
+                       ida->free_bitmap = bitmap;
+                       bitmap = NULL;
+               }
+               spin_unlock_irqrestore(&ida->idr.lock, flags);
+       }
+
+       kfree(bitmap);
+}
+
+/**
+ * ida_pre_get - reserve resources for ida allocation
+ * @ida:       ida handle
+ * @gfp_mask:  memory allocation flag
+ *
+ * This function should be called prior to locking and calling the
+ * following function.  It preallocates enough memory to satisfy the
+ * worst possible allocation.
+ *
+ * If the system is REALLY out of memory this function returns 0,
+ * otherwise 1.
+ */
+int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
+{
+       /* allocate idr_layers */
+       if (!idr_pre_get(&ida->idr, gfp_mask))
+               return 0;
+
+       /* allocate free_bitmap */
+       if (!ida->free_bitmap) {
+               struct ida_bitmap *bitmap;
+
+               bitmap = kmalloc(sizeof(struct ida_bitmap), gfp_mask);
+               if (!bitmap)
+                       return 0;
+
+               free_bitmap(ida, bitmap);
+       }
+
+       return 1;
+}
+EXPORT_SYMBOL(ida_pre_get);
+
+/**
+ * ida_get_new_above - allocate new ID above or equal to a start id
+ * @ida:       ida handle
+ * @staring_id:        id to start search at
+ * @p_id:      pointer to the allocated handle
+ *
+ * Allocate new ID above or equal to @ida.  It should be called with
+ * any required locks.
+ *
+ * If memory is required, it will return -EAGAIN, you should unlock
+ * and go back to the ida_pre_get() call.  If the ida is full, it will
+ * return -ENOSPC.
+ *
+ * @p_id returns a value in the range 0 ... 0x7fffffff.
+ */
+int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
+{
+       struct idr_layer *pa[MAX_LEVEL];
+       struct ida_bitmap *bitmap;
+       unsigned long flags;
+       int idr_id = starting_id / IDA_BITMAP_BITS;
+       int offset = starting_id % IDA_BITMAP_BITS;
+       int t, id;
+
+ restart:
+       /* get vacant slot */
+       t = idr_get_empty_slot(&ida->idr, idr_id, pa);
+       if (t < 0) {
+               if (t == -1)
+                       return -EAGAIN;
+               else /* will be -3 */
+                       return -ENOSPC;
+       }
+
+       if (t * IDA_BITMAP_BITS >= MAX_ID_BIT)
+               return -ENOSPC;
+
+       if (t != idr_id)
+               offset = 0;
+       idr_id = t;
+
+       /* if bitmap isn't there, create a new one */
+       bitmap = (void *)pa[0]->ary[idr_id & IDR_MASK];
+       if (!bitmap) {
+               spin_lock_irqsave(&ida->idr.lock, flags);
+               bitmap = ida->free_bitmap;
+               ida->free_bitmap = NULL;
+               spin_unlock_irqrestore(&ida->idr.lock, flags);
+
+               if (!bitmap)
+                       return -EAGAIN;
+
+               memset(bitmap, 0, sizeof(struct ida_bitmap));
+               pa[0]->ary[idr_id & IDR_MASK] = (void *)bitmap;
+               pa[0]->count++;
+       }
+
+       /* lookup for empty slot */
+       t = find_next_zero_bit(bitmap->bitmap, IDA_BITMAP_BITS, offset);
+       if (t == IDA_BITMAP_BITS) {
+               /* no empty slot after offset, continue to the next chunk */
+               idr_id++;
+               offset = 0;
+               goto restart;
+       }
+
+       id = idr_id * IDA_BITMAP_BITS + t;
+       if (id >= MAX_ID_BIT)
+               return -ENOSPC;
+
+       __set_bit(t, bitmap->bitmap);
+       if (++bitmap->nr_busy == IDA_BITMAP_BITS)
+               idr_mark_full(pa, idr_id);
+
+       *p_id = id;
+
+       /* Each leaf node can handle nearly a thousand slots and the
+        * whole idea of ida is to have small memory foot print.
+        * Throw away extra resources one by one after each successful
+        * allocation.
+        */
+       if (ida->idr.id_free_cnt || ida->free_bitmap) {
+               struct idr_layer *p = alloc_layer(&ida->idr);
+               if (p)
+                       kmem_cache_free(idr_layer_cache, p);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(ida_get_new_above);
+
+/**
+ * ida_get_new - allocate new ID
+ * @ida:       idr handle
+ * @p_id:      pointer to the allocated handle
+ *
+ * Allocate new ID.  It should be called with any required locks.
+ *
+ * If memory is required, it will return -EAGAIN, you should unlock
+ * and go back to the idr_pre_get() call.  If the idr is full, it will
+ * return -ENOSPC.
+ *
+ * @id returns a value in the range 0 ... 0x7fffffff.
+ */
+int ida_get_new(struct ida *ida, int *p_id)
+{
+       return ida_get_new_above(ida, 0, p_id);
+}
+EXPORT_SYMBOL(ida_get_new);
+
+/**
+ * ida_remove - remove the given ID
+ * @ida:       ida handle
+ * @id:                ID to free
+ */
+void ida_remove(struct ida *ida, int id)
+{
+       struct idr_layer *p = ida->idr.top;
+       int shift = (ida->idr.layers - 1) * IDR_BITS;
+       int idr_id = id / IDA_BITMAP_BITS;
+       int offset = id % IDA_BITMAP_BITS;
+       int n;
+       struct ida_bitmap *bitmap;
+
+       /* clear full bits while looking up the leaf idr_layer */
+       while ((shift > 0) && p) {
+               n = (idr_id >> shift) & IDR_MASK;
+               __clear_bit(n, &p->bitmap);
+               p = p->ary[n];
+               shift -= IDR_BITS;
+       }
+
+       if (p == NULL)
+               goto err;
+
+       n = idr_id & IDR_MASK;
+       __clear_bit(n, &p->bitmap);
+
+       bitmap = (void *)p->ary[n];
+       if (!test_bit(offset, bitmap->bitmap))
+               goto err;
+
+       /* update bitmap and remove it if empty */
+       __clear_bit(offset, bitmap->bitmap);
+       if (--bitmap->nr_busy == 0) {
+               __set_bit(n, &p->bitmap);       /* to please idr_remove() */
+               idr_remove(&ida->idr, idr_id);
+               free_bitmap(ida, bitmap);
+       }
+
+       return;
+
+ err:
+       printk(KERN_WARNING
+              "ida_remove called for id=%d which is not allocated.\n", id);
+}
+EXPORT_SYMBOL(ida_remove);
+
+/**
+ * ida_destroy - release all cached layers within an ida tree
+ * ida:                ida handle
+ */
+void ida_destroy(struct ida *ida)
+{
+       idr_destroy(&ida->idr);
+       kfree(ida->free_bitmap);
+}
+EXPORT_SYMBOL(ida_destroy);
+
+/**
+ * ida_init - initialize ida handle
+ * @ida:       ida handle
+ *
+ * This function is use to set up the handle (@ida) that you will pass
+ * to the rest of the functions.
+ */
+void ida_init(struct ida *ida)
+{
+       memset(ida, 0, sizeof(struct ida));
+       idr_init(&ida->idr);
+
+}
+EXPORT_SYMBOL(ida_init);
index ac1520651b9b457d89e96bd2447aae02d6f8bb46..4b08e0ff95c8bf53745cd6d5257476e0d652b92c 100644 (file)
@@ -44,7 +44,7 @@ static int populate_dir(struct kobject * kobj)
        return error;
 }
 
-static int create_dir(struct kobject * kobj, struct dentry *shadow_parent)
+static int create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
 {
        int error = 0;
        if (kobject_name(kobj)) {
@@ -162,7 +162,7 @@ static void unlink(struct kobject * kobj)
  *     @shadow_parent: sysfs directory to add to.
  */
 
-int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
+int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
 {
        int error = 0;
        struct kobject * parent;
@@ -338,7 +338,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
        /* Note : if we want to send the new name alone, not the full path,
         * we could probably use kobject_name(kobj); */
 
-       error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name);
+       error = sysfs_rename_dir(kobj, kobj->parent->sd, new_name);
 
        /* This function is mostly/only used for network interface.
         * Some hotplug package track interfaces by their name and
@@ -361,8 +361,8 @@ out:
  *     @new_name: object's new name
  */
 
-int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent,
-                         const char *new_name)
+int kobject_shadow_rename(struct kobject *kobj,
+                         struct sysfs_dirent *new_parent, const char *new_name)
 {
        int error = 0;
 
@@ -597,10 +597,17 @@ int kset_add(struct kset * k)
 
 int kset_register(struct kset * k)
 {
+       int err;
+
        if (!k)
                return -EINVAL;
+
        kset_init(k);
-       return kset_add(k);
+       err = kset_add(k);
+       if (err)
+               return err;
+       kobject_uevent(&k->kobj, KOBJ_ADD);
+       return 0;
 }
 
 
index 906ed402f7cabda336a73d6d0d297b862b0d2932..9f70c8e8c871c272047fdc4c969f285299b58926 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1023,10 +1023,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
                }
        }
 
-       error = security_file_mmap(file, reqprot, prot, flags);
+       error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
        if (error)
                return error;
-               
+
        /* Clear old maps */
        error = -ENOMEM;
 munmap_back:
index 5d4bd4f95b8e5ef28f269f604b61d133f341d27b..bc7c52efc71bb1d5dddded25b836c4b842a54edf 100644 (file)
@@ -291,6 +291,10 @@ unsigned long do_mremap(unsigned long addr,
                if ((addr <= new_addr) && (addr+old_len) > new_addr)
                        goto out;
 
+               ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+               if (ret)
+                       goto out;
+
                ret = do_munmap(mm, new_addr, new_len);
                if (ret)
                        goto out;
@@ -390,8 +394,13 @@ unsigned long do_mremap(unsigned long addr,
 
                        new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
                                                vma->vm_pgoff, map_flags);
-                       ret = new_addr;
-                       if (new_addr & ~PAGE_MASK)
+                       if (new_addr & ~PAGE_MASK) {
+                               ret = new_addr;
+                               goto out;
+                       }
+
+                       ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+                       if (ret)
                                goto out;
                }
                ret = move_vma(vma, addr, old_len, new_len, new_addr);
index 2b16b00a5b115be2c13897aab5763562312ecb84..989e2e9af5c3adc42cb250409a4b7249288e0df7 100644 (file)
@@ -639,7 +639,7 @@ static int validate_mmap_request(struct file *file,
        }
 
        /* allow the security API to have its say */
-       ret = security_file_mmap(file, reqprot, prot, flags);
+       ret = security_file_mmap(file, reqprot, prot, flags, addr, 0);
        if (ret < 0)
                return ret;
 
index abb9900edb3f189a923315f71ec5991f7d34d079..cda936b77d222b2bb68cc4b79f8ba1e468cd9de3 100644 (file)
@@ -373,10 +373,11 @@ void vlan_setup(struct net_device *new_dev)
        new_dev->open = vlan_dev_open;
        new_dev->stop = vlan_dev_stop;
        new_dev->set_multicast_list = vlan_dev_set_multicast_list;
+       new_dev->change_rx_flags = vlan_change_rx_flags;
        new_dev->destructor = free_netdev;
        new_dev->do_ioctl = vlan_dev_ioctl;
 
-       memset(new_dev->broadcast, 0, sizeof(ETH_ALEN));
+       memset(new_dev->broadcast, 0, ETH_ALEN);
 }
 
 static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev)
index 62ce1c519aab54c5a1a244709e2f87243060d00a..7df5b29355795382e6ceb5d334768f87c37fe9b6 100644 (file)
@@ -69,6 +69,7 @@ int vlan_dev_set_vlan_flag(const struct net_device *dev,
                           u32 flag, short flag_val);
 void vlan_dev_get_realdev_name(const struct net_device *dev, char *result);
 void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result);
+void vlan_change_rx_flags(struct net_device *dev, int change);
 void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
 
 int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id);
index d4a62d1b52b49d45f9f8f3ea932bba210c37692f..4d2aa4dd42ac6d78a3cacd458cdc5da59de30907 100644 (file)
@@ -612,90 +612,6 @@ void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result)
        *result = VLAN_DEV_INFO(dev)->vlan_id;
 }
 
-static inline int vlan_dmi_equals(struct dev_mc_list *dmi1,
-                                 struct dev_mc_list *dmi2)
-{
-       return ((dmi1->dmi_addrlen == dmi2->dmi_addrlen) &&
-               (memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0));
-}
-
-/** dmi is a single entry into a dev_mc_list, a single node.  mc_list is
- *  an entire list, and we'll iterate through it.
- */
-static int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list)
-{
-       struct dev_mc_list *idmi;
-
-       for (idmi = mc_list; idmi != NULL; ) {
-               if (vlan_dmi_equals(dmi, idmi)) {
-                       if (dmi->dmi_users > idmi->dmi_users)
-                               return 1;
-                       else
-                               return 0;
-               } else {
-                       idmi = idmi->next;
-               }
-       }
-
-       return 1;
-}
-
-static inline void vlan_destroy_mc_list(struct dev_mc_list *mc_list)
-{
-       struct dev_mc_list *dmi = mc_list;
-       struct dev_mc_list *next;
-
-       while(dmi) {
-               next = dmi->next;
-               kfree(dmi);
-               dmi = next;
-       }
-}
-
-static void vlan_copy_mc_list(struct dev_mc_list *mc_list, struct vlan_dev_info *vlan_info)
-{
-       struct dev_mc_list *dmi, *new_dmi;
-
-       vlan_destroy_mc_list(vlan_info->old_mc_list);
-       vlan_info->old_mc_list = NULL;
-
-       for (dmi = mc_list; dmi != NULL; dmi = dmi->next) {
-               new_dmi = kmalloc(sizeof(*new_dmi), GFP_ATOMIC);
-               if (new_dmi == NULL) {
-                       printk(KERN_ERR "vlan: cannot allocate memory. "
-                              "Multicast may not work properly from now.\n");
-                       return;
-               }
-
-               /* Copy whole structure, then make new 'next' pointer */
-               *new_dmi = *dmi;
-               new_dmi->next = vlan_info->old_mc_list;
-               vlan_info->old_mc_list = new_dmi;
-       }
-}
-
-static void vlan_flush_mc_list(struct net_device *dev)
-{
-       struct dev_mc_list *dmi = dev->mc_list;
-
-       while (dmi) {
-               printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from vlan interface\n",
-                      dev->name,
-                      dmi->dmi_addr[0],
-                      dmi->dmi_addr[1],
-                      dmi->dmi_addr[2],
-                      dmi->dmi_addr[3],
-                      dmi->dmi_addr[4],
-                      dmi->dmi_addr[5]);
-               dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-               dmi = dev->mc_list;
-       }
-
-       /* dev->mc_list is NULL by the time we get here. */
-       vlan_destroy_mc_list(VLAN_DEV_INFO(dev)->old_mc_list);
-       VLAN_DEV_INFO(dev)->old_mc_list = NULL;
-}
-
 int vlan_dev_open(struct net_device *dev)
 {
        struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
@@ -712,6 +628,11 @@ int vlan_dev_open(struct net_device *dev)
        }
        memcpy(vlan->real_dev_addr, real_dev->dev_addr, ETH_ALEN);
 
+       if (dev->flags & IFF_ALLMULTI)
+               dev_set_allmulti(real_dev, 1);
+       if (dev->flags & IFF_PROMISC)
+               dev_set_promiscuity(real_dev, 1);
+
        return 0;
 }
 
@@ -719,7 +640,11 @@ int vlan_dev_stop(struct net_device *dev)
 {
        struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
 
-       vlan_flush_mc_list(dev);
+       dev_mc_unsync(real_dev, dev);
+       if (dev->flags & IFF_ALLMULTI)
+               dev_set_allmulti(real_dev, -1);
+       if (dev->flags & IFF_PROMISC)
+               dev_set_promiscuity(real_dev, -1);
 
        if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr))
                dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len);
@@ -754,68 +679,18 @@ int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        return err;
 }
 
-/** Taken from Gleb + Lennert's VLAN code, and modified... */
-void vlan_dev_set_multicast_list(struct net_device *vlan_dev)
+void vlan_change_rx_flags(struct net_device *dev, int change)
 {
-       struct dev_mc_list *dmi;
-       struct net_device *real_dev;
-       int inc;
-
-       if (vlan_dev && (vlan_dev->priv_flags & IFF_802_1Q_VLAN)) {
-               /* Then it's a real vlan device, as far as we can tell.. */
-               real_dev = VLAN_DEV_INFO(vlan_dev)->real_dev;
-
-               /* compare the current promiscuity to the last promisc we had.. */
-               inc = vlan_dev->promiscuity - VLAN_DEV_INFO(vlan_dev)->old_promiscuity;
-               if (inc) {
-                       printk(KERN_INFO "%s: dev_set_promiscuity(master, %d)\n",
-                              vlan_dev->name, inc);
-                       dev_set_promiscuity(real_dev, inc); /* found in dev.c */
-                       VLAN_DEV_INFO(vlan_dev)->old_promiscuity = vlan_dev->promiscuity;
-               }
-
-               inc = vlan_dev->allmulti - VLAN_DEV_INFO(vlan_dev)->old_allmulti;
-               if (inc) {
-                       printk(KERN_INFO "%s: dev_set_allmulti(master, %d)\n",
-                              vlan_dev->name, inc);
-                       dev_set_allmulti(real_dev, inc); /* dev.c */
-                       VLAN_DEV_INFO(vlan_dev)->old_allmulti = vlan_dev->allmulti;
-               }
-
-               /* looking for addresses to add to master's list */
-               for (dmi = vlan_dev->mc_list; dmi != NULL; dmi = dmi->next) {
-                       if (vlan_should_add_mc(dmi, VLAN_DEV_INFO(vlan_dev)->old_mc_list)) {
-                               dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-                               printk(KERN_DEBUG "%s: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n",
-                                      vlan_dev->name,
-                                      dmi->dmi_addr[0],
-                                      dmi->dmi_addr[1],
-                                      dmi->dmi_addr[2],
-                                      dmi->dmi_addr[3],
-                                      dmi->dmi_addr[4],
-                                      dmi->dmi_addr[5]);
-                       }
-               }
+       struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
 
-               /* looking for addresses to delete from master's list */
-               for (dmi = VLAN_DEV_INFO(vlan_dev)->old_mc_list; dmi != NULL; dmi = dmi->next) {
-                       if (vlan_should_add_mc(dmi, vlan_dev->mc_list)) {
-                               /* if we think we should add it to the new list, then we should really
-                                * delete it from the real list on the underlying device.
-                                */
-                               dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-                               printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n",
-                                      vlan_dev->name,
-                                      dmi->dmi_addr[0],
-                                      dmi->dmi_addr[1],
-                                      dmi->dmi_addr[2],
-                                      dmi->dmi_addr[3],
-                                      dmi->dmi_addr[4],
-                                      dmi->dmi_addr[5]);
-                       }
-               }
+       if (change & IFF_ALLMULTI)
+               dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1);
+       if (change & IFF_PROMISC)
+               dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1);
+}
 
-               /* save multicast list */
-               vlan_copy_mc_list(vlan_dev->mc_list, VLAN_DEV_INFO(vlan_dev));
-       }
+/** Taken from Gleb + Lennert's VLAN code, and modified... */
+void vlan_dev_set_multicast_list(struct net_device *vlan_dev)
+{
+       dev_mc_sync(VLAN_DEV_INFO(vlan_dev)->real_dev, vlan_dev);
 }
index 33c6c4a7c689d76f25299c0cdb730d33315f8e73..4f42263e0a8a8ba8e3e45d2979f34508b19ecbc4 100644 (file)
@@ -360,8 +360,9 @@ static struct attribute_group bridge_group = {
  *
  * Returns the number of bytes read.
  */
-static ssize_t brforward_read(struct kobject *kobj, char *buf,
-                          loff_t off, size_t count)
+static ssize_t brforward_read(struct kobject *kobj,
+                             struct bin_attribute *bin_attr,
+                             char *buf, loff_t off, size_t count)
 {
        struct device *dev = to_dev(kobj);
        struct net_bridge *br = to_bridge(dev);
@@ -383,8 +384,7 @@ static ssize_t brforward_read(struct kobject *kobj, char *buf,
 
 static struct bin_attribute bridge_forward = {
        .attr = { .name = SYSFS_BRIDGE_FDB,
-                 .mode = S_IRUGO,
-                 .owner = THIS_MODULE, },
+                 .mode = S_IRUGO, },
        .read = brforward_read,
 };
 
index 2da22927d8dd158ea341fe53d896dc1f53ea52b6..79db51fcb4768dabb001c5afb17325c6ad00a634 100644 (file)
@@ -29,8 +29,7 @@ struct brport_attribute {
 #define BRPORT_ATTR(_name,_mode,_show,_store)                  \
 struct brport_attribute brport_attr_##_name = {                \
        .attr = {.name = __stringify(_name),                    \
-                .mode = _mode,                                 \
-                .owner = THIS_MODULE, },                       \
+                .mode = _mode },                               \
        .show   = _show,                                        \
        .store  = _store,                                       \
 };
index 4221dcda88d72c6ceb7435318da76b1c68355fa1..13a0d9f6da54c02cbed38292ddef7eaa1d9241a0 100644 (file)
@@ -98,6 +98,7 @@
 #include <linux/seq_file.h>
 #include <linux/stat.h>
 #include <linux/if_bridge.h>
+#include <linux/if_macvlan.h>
 #include <net/dst.h>
 #include <net/pkt_sched.h>
 #include <net/checksum.h>
@@ -151,9 +152,22 @@ static struct list_head ptype_base[16] __read_mostly;      /* 16 way hashed list */
 static struct list_head ptype_all __read_mostly;       /* Taps */
 
 #ifdef CONFIG_NET_DMA
-static struct dma_client *net_dma_client;
-static unsigned int net_dma_count;
-static spinlock_t net_dma_event_lock;
+struct net_dma {
+       struct dma_client client;
+       spinlock_t lock;
+       cpumask_t channel_mask;
+       struct dma_chan *channels[NR_CPUS];
+};
+
+static enum dma_state_client
+netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
+       enum dma_state state);
+
+static struct net_dma net_dma = {
+       .client = {
+               .event_callback = netdev_dma_event,
+       },
+};
 #endif
 
 /*
@@ -1800,6 +1814,28 @@ static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
 #define handle_bridge(skb, pt_prev, ret, orig_dev)     (skb)
 #endif
 
+#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
+struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *skb) __read_mostly;
+EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook);
+
+static inline struct sk_buff *handle_macvlan(struct sk_buff *skb,
+                                            struct packet_type **pt_prev,
+                                            int *ret,
+                                            struct net_device *orig_dev)
+{
+       if (skb->dev->macvlan_port == NULL)
+               return skb;
+
+       if (*pt_prev) {
+               *ret = deliver_skb(skb, *pt_prev, orig_dev);
+               *pt_prev = NULL;
+       }
+       return macvlan_handle_frame_hook(skb);
+}
+#else
+#define handle_macvlan(skb, pt_prev, ret, orig_dev)    (skb)
+#endif
+
 #ifdef CONFIG_NET_CLS_ACT
 /* TODO: Maybe we should just force sch_ingress to be compiled in
  * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions
@@ -1905,6 +1941,9 @@ ncls:
 #endif
 
        skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
+       if (!skb)
+               goto out;
+       skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev);
        if (!skb)
                goto out;
 
@@ -2022,12 +2061,13 @@ out:
         * There may not be any more sk_buffs coming right now, so push
         * any pending DMA copies to hardware
         */
-       if (net_dma_client) {
-               struct dma_chan *chan;
-               rcu_read_lock();
-               list_for_each_entry_rcu(chan, &net_dma_client->channels, client_node)
-                       dma_async_memcpy_issue_pending(chan);
-               rcu_read_unlock();
+       if (!cpus_empty(net_dma.channel_mask)) {
+               int chan_idx;
+               for_each_cpu_mask(chan_idx, net_dma.channel_mask) {
+                       struct dma_chan *chan = net_dma.channels[chan_idx];
+                       if (chan)
+                               dma_async_memcpy_issue_pending(chan);
+               }
        }
 #endif
        return;
@@ -2507,6 +2547,8 @@ static void __dev_set_promiscuity(struct net_device *dev, int inc)
 {
        unsigned short old_flags = dev->flags;
 
+       ASSERT_RTNL();
+
        if ((dev->promiscuity += inc) == 0)
                dev->flags &= ~IFF_PROMISC;
        else
@@ -2521,6 +2563,9 @@ static void __dev_set_promiscuity(struct net_device *dev, int inc)
                        dev->name, (dev->flags & IFF_PROMISC),
                        (old_flags & IFF_PROMISC),
                        audit_get_loginuid(current->audit_context));
+
+               if (dev->change_rx_flags)
+                       dev->change_rx_flags(dev, IFF_PROMISC);
        }
 }
 
@@ -2559,11 +2604,16 @@ void dev_set_allmulti(struct net_device *dev, int inc)
 {
        unsigned short old_flags = dev->flags;
 
+       ASSERT_RTNL();
+
        dev->flags |= IFF_ALLMULTI;
        if ((dev->allmulti += inc) == 0)
                dev->flags &= ~IFF_ALLMULTI;
-       if (dev->flags ^ old_flags)
+       if (dev->flags ^ old_flags) {
+               if (dev->change_rx_flags)
+                       dev->change_rx_flags(dev, IFF_ALLMULTI);
                dev_set_rx_mode(dev);
+       }
 }
 
 /*
@@ -2764,6 +2814,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
        int ret, changes;
        int old_flags = dev->flags;
 
+       ASSERT_RTNL();
+
        /*
         *      Set the flags on our device.
         */
@@ -2778,6 +2830,9 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
         *      Load in the correct multicast list now the flags have changed.
         */
 
+       if (dev->change_rx_flags && (dev->flags ^ flags) & IFF_MULTICAST)
+               dev->change_rx_flags(dev, IFF_MULTICAST);
+
        dev_set_rx_mode(dev);
 
        /*
@@ -3775,12 +3830,13 @@ static int dev_cpu_callback(struct notifier_block *nfb,
  * This is called when the number of channels allocated to the net_dma_client
  * changes.  The net_dma_client tries to have one DMA channel per CPU.
  */
-static void net_dma_rebalance(void)
+
+static void net_dma_rebalance(struct net_dma *net_dma)
 {
-       unsigned int cpu, i, n;
+       unsigned int cpu, i, n, chan_idx;
        struct dma_chan *chan;
 
-       if (net_dma_count == 0) {
+       if (cpus_empty(net_dma->channel_mask)) {
                for_each_online_cpu(cpu)
                        rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL);
                return;
@@ -3789,10 +3845,12 @@ static void net_dma_rebalance(void)
        i = 0;
        cpu = first_cpu(cpu_online_map);
 
-       rcu_read_lock();
-       list_for_each_entry(chan, &net_dma_client->channels, client_node) {
-               n = ((num_online_cpus() / net_dma_count)
-                  + (i < (num_online_cpus() % net_dma_count) ? 1 : 0));
+       for_each_cpu_mask(chan_idx, net_dma->channel_mask) {
+               chan = net_dma->channels[chan_idx];
+
+               n = ((num_online_cpus() / cpus_weight(net_dma->channel_mask))
+                  + (i < (num_online_cpus() %
+                       cpus_weight(net_dma->channel_mask)) ? 1 : 0));
 
                while(n) {
                        per_cpu(softnet_data, cpu).net_dma = chan;
@@ -3801,7 +3859,6 @@ static void net_dma_rebalance(void)
                }
                i++;
        }
-       rcu_read_unlock();
 }
 
 /**
@@ -3810,23 +3867,53 @@ static void net_dma_rebalance(void)
  * @chan: DMA channel for the event
  * @event: event type
  */
-static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
-       enum dma_event event)
-{
-       spin_lock(&net_dma_event_lock);
-       switch (event) {
-       case DMA_RESOURCE_ADDED:
-               net_dma_count++;
-               net_dma_rebalance();
+static enum dma_state_client
+netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
+       enum dma_state state)
+{
+       int i, found = 0, pos = -1;
+       struct net_dma *net_dma =
+               container_of(client, struct net_dma, client);
+       enum dma_state_client ack = DMA_DUP; /* default: take no action */
+
+       spin_lock(&net_dma->lock);
+       switch (state) {
+       case DMA_RESOURCE_AVAILABLE:
+               for (i = 0; i < NR_CPUS; i++)
+                       if (net_dma->channels[i] == chan) {
+                               found = 1;
+                               break;
+                       } else if (net_dma->channels[i] == NULL && pos < 0)
+                               pos = i;
+
+               if (!found && pos >= 0) {
+                       ack = DMA_ACK;
+                       net_dma->channels[pos] = chan;
+                       cpu_set(pos, net_dma->channel_mask);
+                       net_dma_rebalance(net_dma);
+               }
                break;
        case DMA_RESOURCE_REMOVED:
-               net_dma_count--;
-               net_dma_rebalance();
+               for (i = 0; i < NR_CPUS; i++)
+                       if (net_dma->channels[i] == chan) {
+                               found = 1;
+                               pos = i;
+                               break;
+                       }
+
+               if (found) {
+                       ack = DMA_ACK;
+                       cpu_clear(pos, net_dma->channel_mask);
+                       net_dma->channels[i] = NULL;
+                       net_dma_rebalance(net_dma);
+               }
                break;
        default:
                break;
        }
-       spin_unlock(&net_dma_event_lock);
+       spin_unlock(&net_dma->lock);
+
+       return ack;
 }
 
 /**
@@ -3834,12 +3921,10 @@ static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
  */
 static int __init netdev_dma_register(void)
 {
-       spin_lock_init(&net_dma_event_lock);
-       net_dma_client = dma_async_client_register(netdev_dma_event);
-       if (net_dma_client == NULL)
-               return -ENOMEM;
-
-       dma_async_client_chan_request(net_dma_client, num_online_cpus());
+       spin_lock_init(&net_dma.lock);
+       dma_cap_set(DMA_MEMCPY, net_dma.client.cap_mask);
+       dma_async_client_register(&net_dma.client);
+       dma_async_client_chan_request(&net_dma.client);
        return 0;
 }
 
index aa38100601fb31d2c6d73e83ddb30f62d884c45a..235a2a8a0d05b0b2163c180001f918274720a785 100644 (file)
@@ -102,6 +102,81 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
        return err;
 }
 
+/**
+ *     dev_mc_sync     - Synchronize device's multicast list to another device
+ *     @to: destination device
+ *     @from: source device
+ *
+ *     Add newly added addresses to the destination device and release
+ *     addresses that have no users left. The source device must be
+ *     locked by netif_tx_lock_bh.
+ *
+ *     This function is intended to be called from the dev->set_multicast_list
+ *     function of layered software devices.
+ */
+int dev_mc_sync(struct net_device *to, struct net_device *from)
+{
+       struct dev_addr_list *da;
+       int err = 0;
+
+       netif_tx_lock_bh(to);
+       for (da = from->mc_list; da != NULL; da = da->next) {
+               if (!da->da_synced) {
+                       err = __dev_addr_add(&to->mc_list, &to->mc_count,
+                                            da->da_addr, da->da_addrlen, 0);
+                       if (err < 0)
+                               break;
+                       da->da_synced = 1;
+                       da->da_users++;
+               } else if (da->da_users == 1) {
+                       __dev_addr_delete(&to->mc_list, &to->mc_count,
+                                         da->da_addr, da->da_addrlen, 0);
+                       __dev_addr_delete(&from->mc_list, &from->mc_count,
+                                         da->da_addr, da->da_addrlen, 0);
+               }
+       }
+       if (!err)
+               __dev_set_rx_mode(to);
+       netif_tx_unlock_bh(to);
+
+       return err;
+}
+EXPORT_SYMBOL(dev_mc_sync);
+
+
+/**
+ *     dev_mc_unsync   - Remove synchronized addresses from the destination
+ *                       device
+ *     @to: destination device
+ *     @from: source device
+ *
+ *     Remove all addresses that were added to the destination device by
+ *     dev_mc_sync(). This function is intended to be called from the
+ *     dev->stop function of layered software devices.
+ */
+void dev_mc_unsync(struct net_device *to, struct net_device *from)
+{
+       struct dev_addr_list *da;
+
+       netif_tx_lock_bh(from);
+       netif_tx_lock_bh(to);
+
+       for (da = from->mc_list; da != NULL; da = da->next) {
+               if (!da->da_synced)
+                       continue;
+               __dev_addr_delete(&to->mc_list, &to->mc_count,
+                                 da->da_addr, da->da_addrlen, 0);
+               da->da_synced = 0;
+               __dev_addr_delete(&from->mc_list, &from->mc_count,
+                                 da->da_addr, da->da_addrlen, 0);
+       }
+       __dev_set_rx_mode(to);
+
+       netif_tx_unlock_bh(to);
+       netif_tx_unlock_bh(from);
+}
+EXPORT_SYMBOL(dev_mc_unsync);
+
 /*
  *     Discard multicast list when a device is downed
  */
index 450f44bb2c8e6591b90e846a056dee2a04f8d40a..987b94403be55be814fb5245300236fb0b863558 100644 (file)
@@ -1116,6 +1116,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        long timeo;
        struct task_struct *user_recv = NULL;
        int copied_early = 0;
+       struct sk_buff *skb;
 
        lock_sock(sk);
 
@@ -1142,16 +1143,26 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 #ifdef CONFIG_NET_DMA
        tp->ucopy.dma_chan = NULL;
        preempt_disable();
-       if ((len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
-           !sysctl_tcp_low_latency && __get_cpu_var(softnet_data).net_dma) {
-               preempt_enable_no_resched();
-               tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len);
-       } else
-               preempt_enable_no_resched();
+       skb = skb_peek_tail(&sk->sk_receive_queue);
+       {
+               int available = 0;
+
+               if (skb)
+                       available = TCP_SKB_CB(skb)->seq + skb->len - (*seq);
+               if ((available < target) &&
+                   (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
+                   !sysctl_tcp_low_latency &&
+                   __get_cpu_var(softnet_data).net_dma) {
+                       preempt_enable_no_resched();
+                       tp->ucopy.pinned_list =
+                                       dma_pin_iovec_pages(msg->msg_iov, len);
+               } else {
+                       preempt_enable_no_resched();
+               }
+       }
 #endif
 
        do {
-               struct sk_buff *skb;
                u32 offset;
 
                /* Are we at urgent data? Stop if we have read anything or have SIGURG pending. */
@@ -1439,7 +1450,6 @@ skip_copy:
 
 #ifdef CONFIG_NET_DMA
        if (tp->ucopy.dma_chan) {
-               struct sk_buff *skb;
                dma_cookie_t done, used;
 
                dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
index 86624fabc4bf416c501c3ea1f10124b93c0be295..f37d5928921ad3f156465836f275c38595b9dfbb 100644 (file)
@@ -111,6 +111,7 @@ static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
                        p->snd_una = tp->snd_una;
                        p->snd_cwnd = tp->snd_cwnd;
                        p->snd_wnd = tp->snd_wnd;
+                       p->ssthresh = tcp_current_ssthresh(sk);
                        p->srtt = tp->srtt >> 3;
 
                        tcp_probe.head = (tcp_probe.head + 1) % bufsize;
index e5c840c30284502e809669090c40b8c79126f787..230e35c5978627c351c34b92af08d494a5f02b75 100644 (file)
@@ -55,7 +55,7 @@ static void rfkill_task_handler(struct work_struct *work)
 
 static void rfkill_schedule_toggle(struct rfkill_task *task)
 {
-       unsigned int flags;
+       unsigned long flags;
 
        spin_lock_irqsave(&task->lock, flags);
 
index 9527f2bb17449ea6808f4fffd5f73feace80442f..aa55d0a03e6f559ae7c413487275099ba4e3dbbb 100644 (file)
 #include <linux/errno.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/spinlock.h>
+#include <linux/smp_lock.h>
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY       RPCDBG_AUTH
 #endif
 
-static struct rpc_authops *    auth_flavors[RPC_AUTH_MAXFLAVOR] = {
+static DEFINE_SPINLOCK(rpc_authflavor_lock);
+static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
        &authnull_ops,          /* AUTH_NULL */
        &authunix_ops,          /* AUTH_UNIX */
        NULL,                   /* others can be loadable modules */
 };
 
+static LIST_HEAD(cred_unused);
+static unsigned long number_cred_unused;
+
 static u32
 pseudoflavor_to_flavor(u32 flavor) {
        if (flavor >= RPC_AUTH_MAXFLAVOR)
@@ -32,55 +37,67 @@ pseudoflavor_to_flavor(u32 flavor) {
 }
 
 int
-rpcauth_register(struct rpc_authops *ops)
+rpcauth_register(const struct rpc_authops *ops)
 {
        rpc_authflavor_t flavor;
+       int ret = -EPERM;
 
        if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
                return -EINVAL;
-       if (auth_flavors[flavor] != NULL)
-               return -EPERM;          /* what else? */
-       auth_flavors[flavor] = ops;
-       return 0;
+       spin_lock(&rpc_authflavor_lock);
+       if (auth_flavors[flavor] == NULL) {
+               auth_flavors[flavor] = ops;
+               ret = 0;
+       }
+       spin_unlock(&rpc_authflavor_lock);
+       return ret;
 }
 
 int
-rpcauth_unregister(struct rpc_authops *ops)
+rpcauth_unregister(const struct rpc_authops *ops)
 {
        rpc_authflavor_t flavor;
+       int ret = -EPERM;
 
        if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
                return -EINVAL;
-       if (auth_flavors[flavor] != ops)
-               return -EPERM;          /* what else? */
-       auth_flavors[flavor] = NULL;
-       return 0;
+       spin_lock(&rpc_authflavor_lock);
+       if (auth_flavors[flavor] == ops) {
+               auth_flavors[flavor] = NULL;
+               ret = 0;
+       }
+       spin_unlock(&rpc_authflavor_lock);
+       return ret;
 }
 
 struct rpc_auth *
 rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
 {
        struct rpc_auth         *auth;
-       struct rpc_authops      *ops;
+       const struct rpc_authops *ops;
        u32                     flavor = pseudoflavor_to_flavor(pseudoflavor);
 
        auth = ERR_PTR(-EINVAL);
        if (flavor >= RPC_AUTH_MAXFLAVOR)
                goto out;
 
-       /* FIXME - auth_flavors[] really needs an rw lock,
-        * and module refcounting. */
 #ifdef CONFIG_KMOD
        if ((ops = auth_flavors[flavor]) == NULL)
                request_module("rpc-auth-%u", flavor);
 #endif
-       if ((ops = auth_flavors[flavor]) == NULL)
+       spin_lock(&rpc_authflavor_lock);
+       ops = auth_flavors[flavor];
+       if (ops == NULL || !try_module_get(ops->owner)) {
+               spin_unlock(&rpc_authflavor_lock);
                goto out;
+       }
+       spin_unlock(&rpc_authflavor_lock);
        auth = ops->create(clnt, pseudoflavor);
+       module_put(ops->owner);
        if (IS_ERR(auth))
                return auth;
        if (clnt->cl_auth)
-               rpcauth_destroy(clnt->cl_auth);
+               rpcauth_release(clnt->cl_auth);
        clnt->cl_auth = auth;
 
 out:
@@ -88,7 +105,7 @@ out:
 }
 
 void
-rpcauth_destroy(struct rpc_auth *auth)
+rpcauth_release(struct rpc_auth *auth)
 {
        if (!atomic_dec_and_test(&auth->au_count))
                return;
@@ -97,11 +114,31 @@ rpcauth_destroy(struct rpc_auth *auth)
 
 static DEFINE_SPINLOCK(rpc_credcache_lock);
 
+static void
+rpcauth_unhash_cred_locked(struct rpc_cred *cred)
+{
+       hlist_del_rcu(&cred->cr_hash);
+       smp_mb__before_clear_bit();
+       clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
+}
+
+static void
+rpcauth_unhash_cred(struct rpc_cred *cred)
+{
+       spinlock_t *cache_lock;
+
+       cache_lock = &cred->cr_auth->au_credcache->lock;
+       spin_lock(cache_lock);
+       if (atomic_read(&cred->cr_count) == 0)
+               rpcauth_unhash_cred_locked(cred);
+       spin_unlock(cache_lock);
+}
+
 /*
  * Initialize RPC credential cache
  */
 int
-rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
+rpcauth_init_credcache(struct rpc_auth *auth)
 {
        struct rpc_cred_cache *new;
        int i;
@@ -111,8 +148,7 @@ rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
                return -ENOMEM;
        for (i = 0; i < RPC_CREDCACHE_NR; i++)
                INIT_HLIST_HEAD(&new->hashtable[i]);
-       new->expire = expire;
-       new->nextgc = jiffies + (expire >> 1);
+       spin_lock_init(&new->lock);
        auth->au_credcache = new;
        return 0;
 }
@@ -121,13 +157,13 @@ rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
  * Destroy a list of credentials
  */
 static inline
-void rpcauth_destroy_credlist(struct hlist_head *head)
+void rpcauth_destroy_credlist(struct list_head *head)
 {
        struct rpc_cred *cred;
 
-       while (!hlist_empty(head)) {
-               cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
-               hlist_del_init(&cred->cr_hash);
+       while (!list_empty(head)) {
+               cred = list_entry(head->next, struct rpc_cred, cr_lru);
+               list_del_init(&cred->cr_lru);
                put_rpccred(cred);
        }
 }
@@ -137,58 +173,95 @@ void rpcauth_destroy_credlist(struct hlist_head *head)
  * that are not referenced.
  */
 void
-rpcauth_free_credcache(struct rpc_auth *auth)
+rpcauth_clear_credcache(struct rpc_cred_cache *cache)
 {
-       struct rpc_cred_cache *cache = auth->au_credcache;
-       HLIST_HEAD(free);
-       struct hlist_node *pos, *next;
+       LIST_HEAD(free);
+       struct hlist_head *head;
        struct rpc_cred *cred;
        int             i;
 
        spin_lock(&rpc_credcache_lock);
+       spin_lock(&cache->lock);
        for (i = 0; i < RPC_CREDCACHE_NR; i++) {
-               hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
-                       cred = hlist_entry(pos, struct rpc_cred, cr_hash);
-                       __hlist_del(&cred->cr_hash);
-                       hlist_add_head(&cred->cr_hash, &free);
+               head = &cache->hashtable[i];
+               while (!hlist_empty(head)) {
+                       cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
+                       get_rpccred(cred);
+                       if (!list_empty(&cred->cr_lru)) {
+                               list_del(&cred->cr_lru);
+                               number_cred_unused--;
+                       }
+                       list_add_tail(&cred->cr_lru, &free);
+                       rpcauth_unhash_cred_locked(cred);
                }
        }
+       spin_unlock(&cache->lock);
        spin_unlock(&rpc_credcache_lock);
        rpcauth_destroy_credlist(&free);
 }
 
-static void
-rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist_head *free)
+/*
+ * Destroy the RPC credential cache
+ */
+void
+rpcauth_destroy_credcache(struct rpc_auth *auth)
 {
-       if (atomic_read(&cred->cr_count) != 1)
-              return;
-       if (time_after(jiffies, cred->cr_expire + auth->au_credcache->expire))
-               cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-       if (!(cred->cr_flags & RPCAUTH_CRED_UPTODATE)) {
-               __hlist_del(&cred->cr_hash);
-               hlist_add_head(&cred->cr_hash, free);
+       struct rpc_cred_cache *cache = auth->au_credcache;
+
+       if (cache) {
+               auth->au_credcache = NULL;
+               rpcauth_clear_credcache(cache);
+               kfree(cache);
        }
 }
 
 /*
  * Remove stale credentials. Avoid sleeping inside the loop.
  */
-static void
-rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free)
+static int
+rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
 {
-       struct rpc_cred_cache *cache = auth->au_credcache;
-       struct hlist_node *pos, *next;
-       struct rpc_cred *cred;
-       int             i;
+       spinlock_t *cache_lock;
+       struct rpc_cred *cred;
 
-       dprintk("RPC:       gc'ing RPC credentials for auth %p\n", auth);
-       for (i = 0; i < RPC_CREDCACHE_NR; i++) {
-               hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
-                       cred = hlist_entry(pos, struct rpc_cred, cr_hash);
-                       rpcauth_prune_expired(auth, cred, free);
+       while (!list_empty(&cred_unused)) {
+               cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
+               list_del_init(&cred->cr_lru);
+               number_cred_unused--;
+               if (atomic_read(&cred->cr_count) != 0)
+                       continue;
+               cache_lock = &cred->cr_auth->au_credcache->lock;
+               spin_lock(cache_lock);
+               if (atomic_read(&cred->cr_count) == 0) {
+                       get_rpccred(cred);
+                       list_add_tail(&cred->cr_lru, free);
+                       rpcauth_unhash_cred_locked(cred);
+                       nr_to_scan--;
                }
+               spin_unlock(cache_lock);
+               if (nr_to_scan == 0)
+                       break;
        }
-       cache->nextgc = jiffies + cache->expire;
+       return nr_to_scan;
+}
+
+/*
+ * Run memory cache shrinker.
+ */
+static int
+rpcauth_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
+{
+       LIST_HEAD(free);
+       int res;
+
+       if (list_empty(&cred_unused))
+               return 0;
+       spin_lock(&rpc_credcache_lock);
+       nr_to_scan = rpcauth_prune_expired(&free, nr_to_scan);
+       res = (number_cred_unused / 100) * sysctl_vfs_cache_pressure;
+       spin_unlock(&rpc_credcache_lock);
+       rpcauth_destroy_credlist(&free);
+       return res;
 }
 
 /*
@@ -198,53 +271,56 @@ struct rpc_cred *
 rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
                int flags)
 {
+       LIST_HEAD(free);
        struct rpc_cred_cache *cache = auth->au_credcache;
-       HLIST_HEAD(free);
-       struct hlist_node *pos, *next;
-       struct rpc_cred *new = NULL,
-                       *cred = NULL;
+       struct hlist_node *pos;
+       struct rpc_cred *cred = NULL,
+                       *entry, *new;
        int             nr = 0;
 
        if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS))
                nr = acred->uid & RPC_CREDCACHE_MASK;
-retry:
-       spin_lock(&rpc_credcache_lock);
-       if (time_before(cache->nextgc, jiffies))
-               rpcauth_gc_credcache(auth, &free);
-       hlist_for_each_safe(pos, next, &cache->hashtable[nr]) {
-               struct rpc_cred *entry;
-               entry = hlist_entry(pos, struct rpc_cred, cr_hash);
-               if (entry->cr_ops->crmatch(acred, entry, flags)) {
-                       hlist_del(&entry->cr_hash);
-                       cred = entry;
-                       break;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
+               if (!entry->cr_ops->crmatch(acred, entry, flags))
+                       continue;
+               spin_lock(&cache->lock);
+               if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) {
+                       spin_unlock(&cache->lock);
+                       continue;
                }
-               rpcauth_prune_expired(auth, entry, &free);
+               cred = get_rpccred(entry);
+               spin_unlock(&cache->lock);
+               break;
        }
-       if (new) {
-               if (cred)
-                       hlist_add_head(&new->cr_hash, &free);
-               else
-                       cred = new;
-       }
-       if (cred) {
-               hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]);
-               get_rpccred(cred);
-       }
-       spin_unlock(&rpc_credcache_lock);
+       rcu_read_unlock();
 
-       rpcauth_destroy_credlist(&free);
+       if (cred != NULL)
+               goto found;
 
-       if (!cred) {
-               new = auth->au_ops->crcreate(auth, acred, flags);
-               if (!IS_ERR(new)) {
-#ifdef RPC_DEBUG
-                       new->cr_magic = RPCAUTH_CRED_MAGIC;
-#endif
-                       goto retry;
-               } else
-                       cred = new;
-       } else if ((cred->cr_flags & RPCAUTH_CRED_NEW)
+       new = auth->au_ops->crcreate(auth, acred, flags);
+       if (IS_ERR(new)) {
+               cred = new;
+               goto out;
+       }
+
+       spin_lock(&cache->lock);
+       hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) {
+               if (!entry->cr_ops->crmatch(acred, entry, flags))
+                       continue;
+               cred = get_rpccred(entry);
+               break;
+       }
+       if (cred == NULL) {
+               cred = new;
+               set_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
+               hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]);
+       } else
+               list_add_tail(&new->cr_lru, &free);
+       spin_unlock(&cache->lock);
+found:
+       if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)
                        && cred->cr_ops->cr_init != NULL
                        && !(flags & RPCAUTH_LOOKUP_NEW)) {
                int res = cred->cr_ops->cr_init(auth, cred);
@@ -253,8 +329,9 @@ retry:
                        cred = ERR_PTR(res);
                }
        }
-
-       return (struct rpc_cred *) cred;
+       rpcauth_destroy_credlist(&free);
+out:
+       return cred;
 }
 
 struct rpc_cred *
@@ -275,10 +352,27 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags)
        return ret;
 }
 
+void
+rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
+                 struct rpc_auth *auth, const struct rpc_credops *ops)
+{
+       INIT_HLIST_NODE(&cred->cr_hash);
+       INIT_LIST_HEAD(&cred->cr_lru);
+       atomic_set(&cred->cr_count, 1);
+       cred->cr_auth = auth;
+       cred->cr_ops = ops;
+       cred->cr_expire = jiffies;
+#ifdef RPC_DEBUG
+       cred->cr_magic = RPCAUTH_CRED_MAGIC;
+#endif
+       cred->cr_uid = acred->uid;
+}
+EXPORT_SYMBOL(rpcauth_init_cred);
+
 struct rpc_cred *
 rpcauth_bindcred(struct rpc_task *task)
 {
-       struct rpc_auth *auth = task->tk_auth;
+       struct rpc_auth *auth = task->tk_client->cl_auth;
        struct auth_cred acred = {
                .uid = current->fsuid,
                .gid = current->fsgid,
@@ -288,7 +382,7 @@ rpcauth_bindcred(struct rpc_task *task)
        int flags = 0;
 
        dprintk("RPC: %5u looking up %s cred\n",
-               task->tk_pid, task->tk_auth->au_ops->au_name);
+               task->tk_pid, task->tk_client->cl_auth->au_ops->au_name);
        get_group_info(acred.group_info);
        if (task->tk_flags & RPC_TASK_ROOTCREDS)
                flags |= RPCAUTH_LOOKUP_ROOTCREDS;
@@ -304,19 +398,42 @@ rpcauth_bindcred(struct rpc_task *task)
 void
 rpcauth_holdcred(struct rpc_task *task)
 {
-       dprintk("RPC: %5u holding %s cred %p\n",
-               task->tk_pid, task->tk_auth->au_ops->au_name,
-               task->tk_msg.rpc_cred);
-       if (task->tk_msg.rpc_cred)
-               get_rpccred(task->tk_msg.rpc_cred);
+       struct rpc_cred *cred = task->tk_msg.rpc_cred;
+       if (cred != NULL) {
+               get_rpccred(cred);
+               dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid,
+                               cred->cr_auth->au_ops->au_name, cred);
+       }
 }
 
 void
 put_rpccred(struct rpc_cred *cred)
 {
-       cred->cr_expire = jiffies;
+       /* Fast path for unhashed credentials */
+       if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
+               goto need_lock;
+
        if (!atomic_dec_and_test(&cred->cr_count))
                return;
+       goto out_destroy;
+need_lock:
+       if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
+               return;
+       if (!list_empty(&cred->cr_lru)) {
+               number_cred_unused--;
+               list_del_init(&cred->cr_lru);
+       }
+       if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
+               rpcauth_unhash_cred(cred);
+       else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
+               cred->cr_expire = jiffies;
+               list_add_tail(&cred->cr_lru, &cred_unused);
+               number_cred_unused++;
+               spin_unlock(&rpc_credcache_lock);
+               return;
+       }
+       spin_unlock(&rpc_credcache_lock);
+out_destroy:
        cred->cr_ops->crdestroy(cred);
 }
 
@@ -326,7 +443,7 @@ rpcauth_unbindcred(struct rpc_task *task)
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
        dprintk("RPC: %5u releasing %s cred %p\n",
-               task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+               task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 
        put_rpccred(cred);
        task->tk_msg.rpc_cred = NULL;
@@ -338,7 +455,7 @@ rpcauth_marshcred(struct rpc_task *task, __be32 *p)
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
        dprintk("RPC: %5u marshaling %s cred %p\n",
-               task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+               task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 
        return cred->cr_ops->crmarshal(task, p);
 }
@@ -349,7 +466,7 @@ rpcauth_checkverf(struct rpc_task *task, __be32 *p)
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
        dprintk("RPC: %5u validating %s cred %p\n",
-               task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+               task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 
        return cred->cr_ops->crvalidate(task, p);
 }
@@ -359,13 +476,17 @@ rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
                __be32 *data, void *obj)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
+       int ret;
 
        dprintk("RPC: %5u using %s cred %p to wrap rpc data\n",
                        task->tk_pid, cred->cr_ops->cr_name, cred);
        if (cred->cr_ops->crwrap_req)
                return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
        /* By default, we encode the arguments normally. */
-       return encode(rqstp, data, obj);
+       lock_kernel();
+       ret = encode(rqstp, data, obj);
+       unlock_kernel();
+       return ret;
 }
 
 int
@@ -373,6 +494,7 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
                __be32 *data, void *obj)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
+       int ret;
 
        dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n",
                        task->tk_pid, cred->cr_ops->cr_name, cred);
@@ -380,7 +502,10 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
                return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
                                                   data, obj);
        /* By default, we decode the arguments normally. */
-       return decode(rqstp, data, obj);
+       lock_kernel();
+       ret = decode(rqstp, data, obj);
+       unlock_kernel();
+       return ret;
 }
 
 int
@@ -390,7 +515,7 @@ rpcauth_refreshcred(struct rpc_task *task)
        int err;
 
        dprintk("RPC: %5u refreshing %s cred %p\n",
-               task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+               task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 
        err = cred->cr_ops->crrefresh(task);
        if (err < 0)
@@ -401,17 +526,34 @@ rpcauth_refreshcred(struct rpc_task *task)
 void
 rpcauth_invalcred(struct rpc_task *task)
 {
+       struct rpc_cred *cred = task->tk_msg.rpc_cred;
+
        dprintk("RPC: %5u invalidating %s cred %p\n",
-               task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred);
-       spin_lock(&rpc_credcache_lock);
-       if (task->tk_msg.rpc_cred)
-               task->tk_msg.rpc_cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-       spin_unlock(&rpc_credcache_lock);
+               task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
+       if (cred)
+               clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
 }
 
 int
 rpcauth_uptodatecred(struct rpc_task *task)
 {
-       return !(task->tk_msg.rpc_cred) ||
-               (task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE);
+       struct rpc_cred *cred = task->tk_msg.rpc_cred;
+
+       return cred == NULL ||
+               test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
+}
+
+
+static struct shrinker *rpc_cred_shrinker;
+
+void __init rpcauth_init_module(void)
+{
+       rpc_init_authunix();
+       rpc_cred_shrinker = set_shrinker(DEFAULT_SEEKS, rpcauth_cache_shrinker);
+}
+
+void __exit rpcauth_remove_module(void)
+{
+       if (rpc_cred_shrinker != NULL)
+               remove_shrinker(rpc_cred_shrinker);
 }
index 4e4ccc5b6fea905131bab2cc6d1a7dd39fd14b97..baf4096d52d491733ce22d5c773820410e5c62af 100644 (file)
 #include <linux/sunrpc/gss_api.h>
 #include <asm/uaccess.h>
 
-static struct rpc_authops authgss_ops;
+static const struct rpc_authops authgss_ops;
 
-static struct rpc_credops gss_credops;
+static const struct rpc_credops gss_credops;
+static const struct rpc_credops gss_nullops;
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY       RPCDBG_AUTH
@@ -64,7 +65,6 @@ static struct rpc_credops gss_credops;
 
 #define NFS_NGROUPS    16
 
-#define GSS_CRED_EXPIRE                (60 * HZ)       /* XXX: reasonable? */
 #define GSS_CRED_SLACK         1024            /* XXX: unused */
 /* length of a krb5 verifier (48), plus data added before arguments when
  * using integrity (two 4-byte integers): */
@@ -79,19 +79,16 @@ static struct rpc_credops gss_credops;
 /* dump the buffer in `emacs-hexl' style */
 #define isprint(c)      ((c > 0x1f) && (c < 0x7f))
 
-static DEFINE_RWLOCK(gss_ctx_lock);
-
 struct gss_auth {
+       struct kref kref;
        struct rpc_auth rpc_auth;
        struct gss_api_mech *mech;
        enum rpc_gss_svc service;
-       struct list_head upcalls;
        struct rpc_clnt *client;
        struct dentry *dentry;
-       spinlock_t lock;
 };
 
-static void gss_destroy_ctx(struct gss_cl_ctx *);
+static void gss_free_ctx(struct gss_cl_ctx *);
 static struct rpc_pipe_ops gss_upcall_ops;
 
 static inline struct gss_cl_ctx *
@@ -105,20 +102,24 @@ static inline void
 gss_put_ctx(struct gss_cl_ctx *ctx)
 {
        if (atomic_dec_and_test(&ctx->count))
-               gss_destroy_ctx(ctx);
+               gss_free_ctx(ctx);
 }
 
+/* gss_cred_set_ctx:
+ * called by gss_upcall_callback and gss_create_upcall in order
+ * to set the gss context. The actual exchange of an old context
+ * and a new one is protected by the inode->i_lock.
+ */
 static void
 gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
 {
        struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
        struct gss_cl_ctx *old;
-       write_lock(&gss_ctx_lock);
+
        old = gss_cred->gc_ctx;
-       gss_cred->gc_ctx = ctx;
-       cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
-       cred->cr_flags &= ~RPCAUTH_CRED_NEW;
-       write_unlock(&gss_ctx_lock);
+       rcu_assign_pointer(gss_cred->gc_ctx, ctx);
+       set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+       clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
        if (old)
                gss_put_ctx(old);
 }
@@ -129,10 +130,10 @@ gss_cred_is_uptodate_ctx(struct rpc_cred *cred)
        struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
        int res = 0;
 
-       read_lock(&gss_ctx_lock);
-       if ((cred->cr_flags & RPCAUTH_CRED_UPTODATE) && gss_cred->gc_ctx)
+       rcu_read_lock();
+       if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx)
                res = 1;
-       read_unlock(&gss_ctx_lock);
+       rcu_read_unlock();
        return res;
 }
 
@@ -171,10 +172,10 @@ gss_cred_get_ctx(struct rpc_cred *cred)
        struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
        struct gss_cl_ctx *ctx = NULL;
 
-       read_lock(&gss_ctx_lock);
+       rcu_read_lock();
        if (gss_cred->gc_ctx)
                ctx = gss_get_ctx(gss_cred->gc_ctx);
-       read_unlock(&gss_ctx_lock);
+       rcu_read_unlock();
        return ctx;
 }
 
@@ -269,10 +270,10 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
 }
 
 static struct gss_upcall_msg *
-__gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
+__gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
 {
        struct gss_upcall_msg *pos;
-       list_for_each_entry(pos, &gss_auth->upcalls, list) {
+       list_for_each_entry(pos, &rpci->in_downcall, list) {
                if (pos->uid != uid)
                        continue;
                atomic_inc(&pos->count);
@@ -290,24 +291,24 @@ __gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
 static inline struct gss_upcall_msg *
 gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
 {
+       struct inode *inode = gss_auth->dentry->d_inode;
+       struct rpc_inode *rpci = RPC_I(inode);
        struct gss_upcall_msg *old;
 
-       spin_lock(&gss_auth->lock);
-       old = __gss_find_upcall(gss_auth, gss_msg->uid);
+       spin_lock(&inode->i_lock);
+       old = __gss_find_upcall(rpci, gss_msg->uid);
        if (old == NULL) {
                atomic_inc(&gss_msg->count);
-               list_add(&gss_msg->list, &gss_auth->upcalls);
+               list_add(&gss_msg->list, &rpci->in_downcall);
        } else
                gss_msg = old;
-       spin_unlock(&gss_auth->lock);
+       spin_unlock(&inode->i_lock);
        return gss_msg;
 }
 
 static void
 __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
 {
-       if (list_empty(&gss_msg->list))
-               return;
        list_del_init(&gss_msg->list);
        rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
        wake_up_all(&gss_msg->waitqueue);
@@ -318,10 +319,14 @@ static void
 gss_unhash_msg(struct gss_upcall_msg *gss_msg)
 {
        struct gss_auth *gss_auth = gss_msg->auth;
+       struct inode *inode = gss_auth->dentry->d_inode;
 
-       spin_lock(&gss_auth->lock);
-       __gss_unhash_msg(gss_msg);
-       spin_unlock(&gss_auth->lock);
+       if (list_empty(&gss_msg->list))
+               return;
+       spin_lock(&inode->i_lock);
+       if (!list_empty(&gss_msg->list))
+               __gss_unhash_msg(gss_msg);
+       spin_unlock(&inode->i_lock);
 }
 
 static void
@@ -330,16 +335,16 @@ gss_upcall_callback(struct rpc_task *task)
        struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred,
                        struct gss_cred, gc_base);
        struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall;
+       struct inode *inode = gss_msg->auth->dentry->d_inode;
 
-       BUG_ON(gss_msg == NULL);
+       spin_lock(&inode->i_lock);
        if (gss_msg->ctx)
                gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
        else
                task->tk_status = gss_msg->msg.errno;
-       spin_lock(&gss_msg->auth->lock);
        gss_cred->gc_upcall = NULL;
        rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
-       spin_unlock(&gss_msg->auth->lock);
+       spin_unlock(&inode->i_lock);
        gss_release_msg(gss_msg);
 }
 
@@ -386,11 +391,12 @@ static inline int
 gss_refresh_upcall(struct rpc_task *task)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
-       struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth,
+       struct gss_auth *gss_auth = container_of(cred->cr_auth,
                        struct gss_auth, rpc_auth);
        struct gss_cred *gss_cred = container_of(cred,
                        struct gss_cred, gc_base);
        struct gss_upcall_msg *gss_msg;
+       struct inode *inode = gss_auth->dentry->d_inode;
        int err = 0;
 
        dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
@@ -400,7 +406,7 @@ gss_refresh_upcall(struct rpc_task *task)
                err = PTR_ERR(gss_msg);
                goto out;
        }
-       spin_lock(&gss_auth->lock);
+       spin_lock(&inode->i_lock);
        if (gss_cred->gc_upcall != NULL)
                rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
        else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
@@ -411,7 +417,7 @@ gss_refresh_upcall(struct rpc_task *task)
                rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
        } else
                err = gss_msg->msg.errno;
-       spin_unlock(&gss_auth->lock);
+       spin_unlock(&inode->i_lock);
        gss_release_msg(gss_msg);
 out:
        dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n",
@@ -422,6 +428,7 @@ out:
 static inline int
 gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
 {
+       struct inode *inode = gss_auth->dentry->d_inode;
        struct rpc_cred *cred = &gss_cred->gc_base;
        struct gss_upcall_msg *gss_msg;
        DEFINE_WAIT(wait);
@@ -435,12 +442,11 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
        }
        for (;;) {
                prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
-               spin_lock(&gss_auth->lock);
+               spin_lock(&inode->i_lock);
                if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {
-                       spin_unlock(&gss_auth->lock);
                        break;
                }
-               spin_unlock(&gss_auth->lock);
+               spin_unlock(&inode->i_lock);
                if (signalled()) {
                        err = -ERESTARTSYS;
                        goto out_intr;
@@ -451,6 +457,7 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
                gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));
        else
                err = gss_msg->msg.errno;
+       spin_unlock(&inode->i_lock);
 out_intr:
        finish_wait(&gss_msg->waitqueue, &wait);
        gss_release_msg(gss_msg);
@@ -489,12 +496,11 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        const void *p, *end;
        void *buf;
        struct rpc_clnt *clnt;
-       struct gss_auth *gss_auth;
-       struct rpc_cred *cred;
        struct gss_upcall_msg *gss_msg;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct gss_cl_ctx *ctx;
        uid_t uid;
-       int err = -EFBIG;
+       ssize_t err = -EFBIG;
 
        if (mlen > MSG_BUF_MAXSIZE)
                goto out;
@@ -503,7 +509,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        if (!buf)
                goto out;
 
-       clnt = RPC_I(filp->f_path.dentry->d_inode)->private;
+       clnt = RPC_I(inode)->private;
        err = -EFAULT;
        if (copy_from_user(buf, src, mlen))
                goto err;
@@ -519,43 +525,38 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        ctx = gss_alloc_context();
        if (ctx == NULL)
                goto err;
-       err = 0;
-       gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);
-       p = gss_fill_context(p, end, ctx, gss_auth->mech);
+
+       err = -ENOENT;
+       /* Find a matching upcall */
+       spin_lock(&inode->i_lock);
+       gss_msg = __gss_find_upcall(RPC_I(inode), uid);
+       if (gss_msg == NULL) {
+               spin_unlock(&inode->i_lock);
+               goto err_put_ctx;
+       }
+       list_del_init(&gss_msg->list);
+       spin_unlock(&inode->i_lock);
+
+       p = gss_fill_context(p, end, ctx, gss_msg->auth->mech);
        if (IS_ERR(p)) {
                err = PTR_ERR(p);
-               if (err != -EACCES)
-                       goto err_put_ctx;
-       }
-       spin_lock(&gss_auth->lock);
-       gss_msg = __gss_find_upcall(gss_auth, uid);
-       if (gss_msg) {
-               if (err == 0 && gss_msg->ctx == NULL)
-                       gss_msg->ctx = gss_get_ctx(ctx);
-               gss_msg->msg.errno = err;
-               __gss_unhash_msg(gss_msg);
-               spin_unlock(&gss_auth->lock);
-               gss_release_msg(gss_msg);
-       } else {
-               struct auth_cred acred = { .uid = uid };
-               spin_unlock(&gss_auth->lock);
-               cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW);
-               if (IS_ERR(cred)) {
-                       err = PTR_ERR(cred);
-                       goto err_put_ctx;
-               }
-               gss_cred_set_ctx(cred, gss_get_ctx(ctx));
+               gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN;
+               goto err_release_msg;
        }
-       gss_put_ctx(ctx);
-       kfree(buf);
-       dprintk("RPC:       gss_pipe_downcall returning length %Zu\n", mlen);
-       return mlen;
+       gss_msg->ctx = gss_get_ctx(ctx);
+       err = mlen;
+
+err_release_msg:
+       spin_lock(&inode->i_lock);
+       __gss_unhash_msg(gss_msg);
+       spin_unlock(&inode->i_lock);
+       gss_release_msg(gss_msg);
 err_put_ctx:
        gss_put_ctx(ctx);
 err:
        kfree(buf);
 out:
-       dprintk("RPC:       gss_pipe_downcall returning %d\n", err);
+       dprintk("RPC:       gss_pipe_downcall returning %Zd\n", err);
        return err;
 }
 
@@ -563,27 +564,21 @@ static void
 gss_pipe_release(struct inode *inode)
 {
        struct rpc_inode *rpci = RPC_I(inode);
-       struct rpc_clnt *clnt;
-       struct rpc_auth *auth;
-       struct gss_auth *gss_auth;
+       struct gss_upcall_msg *gss_msg;
 
-       clnt = rpci->private;
-       auth = clnt->cl_auth;
-       gss_auth = container_of(auth, struct gss_auth, rpc_auth);
-       spin_lock(&gss_auth->lock);
-       while (!list_empty(&gss_auth->upcalls)) {
-               struct gss_upcall_msg *gss_msg;
+       spin_lock(&inode->i_lock);
+       while (!list_empty(&rpci->in_downcall)) {
 
-               gss_msg = list_entry(gss_auth->upcalls.next,
+               gss_msg = list_entry(rpci->in_downcall.next,
                                struct gss_upcall_msg, list);
                gss_msg->msg.errno = -EPIPE;
                atomic_inc(&gss_msg->count);
                __gss_unhash_msg(gss_msg);
-               spin_unlock(&gss_auth->lock);
+               spin_unlock(&inode->i_lock);
                gss_release_msg(gss_msg);
-               spin_lock(&gss_auth->lock);
+               spin_lock(&inode->i_lock);
        }
-       spin_unlock(&gss_auth->lock);
+       spin_unlock(&inode->i_lock);
 }
 
 static void
@@ -637,18 +632,13 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
        gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
        if (gss_auth->service == 0)
                goto err_put_mech;
-       INIT_LIST_HEAD(&gss_auth->upcalls);
-       spin_lock_init(&gss_auth->lock);
        auth = &gss_auth->rpc_auth;
        auth->au_cslack = GSS_CRED_SLACK >> 2;
        auth->au_rslack = GSS_VERF_SLACK >> 2;
        auth->au_ops = &authgss_ops;
        auth->au_flavor = flavor;
        atomic_set(&auth->au_count, 1);
-
-       err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE);
-       if (err)
-               goto err_put_mech;
+       kref_init(&gss_auth->kref);
 
        gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name,
                        clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
@@ -657,7 +647,13 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
                goto err_put_mech;
        }
 
+       err = rpcauth_init_credcache(auth);
+       if (err)
+               goto err_unlink_pipe;
+
        return auth;
+err_unlink_pipe:
+       rpc_unlink(gss_auth->dentry);
 err_put_mech:
        gss_mech_put(gss_auth->mech);
 err_free:
@@ -667,6 +663,25 @@ out_dec:
        return ERR_PTR(err);
 }
 
+static void
+gss_free(struct gss_auth *gss_auth)
+{
+       rpc_unlink(gss_auth->dentry);
+       gss_auth->dentry = NULL;
+       gss_mech_put(gss_auth->mech);
+
+       kfree(gss_auth);
+       module_put(THIS_MODULE);
+}
+
+static void
+gss_free_callback(struct kref *kref)
+{
+       struct gss_auth *gss_auth = container_of(kref, struct gss_auth, kref);
+
+       gss_free(gss_auth);
+}
+
 static void
 gss_destroy(struct rpc_auth *auth)
 {
@@ -675,23 +690,51 @@ gss_destroy(struct rpc_auth *auth)
        dprintk("RPC:       destroying GSS authenticator %p flavor %d\n",
                        auth, auth->au_flavor);
 
+       rpcauth_destroy_credcache(auth);
+
        gss_auth = container_of(auth, struct gss_auth, rpc_auth);
-       rpc_unlink(gss_auth->dentry);
-       gss_auth->dentry = NULL;
-       gss_mech_put(gss_auth->mech);
+       kref_put(&gss_auth->kref, gss_free_callback);
+}
 
-       rpcauth_free_credcache(auth);
-       kfree(gss_auth);
-       module_put(THIS_MODULE);
+/*
+ * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call
+ * to the server with the GSS control procedure field set to
+ * RPC_GSS_PROC_DESTROY. This should normally cause the server to release
+ * all RPCSEC_GSS state associated with that context.
+ */
+static int
+gss_destroying_context(struct rpc_cred *cred)
+{
+       struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
+       struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
+       struct rpc_task *task;
+
+       if (gss_cred->gc_ctx == NULL ||
+                       gss_cred->gc_ctx->gc_proc == RPC_GSS_PROC_DESTROY)
+               return 0;
+
+       gss_cred->gc_ctx->gc_proc = RPC_GSS_PROC_DESTROY;
+       cred->cr_ops = &gss_nullops;
+
+       /* Take a reference to ensure the cred will be destroyed either
+        * by the RPC call or by the put_rpccred() below */
+       get_rpccred(cred);
+
+       task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC);
+       if (!IS_ERR(task))
+               rpc_put_task(task);
+
+       put_rpccred(cred);
+       return 1;
 }
 
-/* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure
+/* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure
  * to create a new cred or context, so they check that things have been
  * allocated before freeing them. */
 static void
-gss_destroy_ctx(struct gss_cl_ctx *ctx)
+gss_do_free_ctx(struct gss_cl_ctx *ctx)
 {
-       dprintk("RPC:       gss_destroy_ctx\n");
+       dprintk("RPC:       gss_free_ctx\n");
 
        if (ctx->gc_gss_ctx)
                gss_delete_sec_context(&ctx->gc_gss_ctx);
@@ -701,15 +744,46 @@ gss_destroy_ctx(struct gss_cl_ctx *ctx)
 }
 
 static void
-gss_destroy_cred(struct rpc_cred *rc)
+gss_free_ctx_callback(struct rcu_head *head)
 {
-       struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base);
+       struct gss_cl_ctx *ctx = container_of(head, struct gss_cl_ctx, gc_rcu);
+       gss_do_free_ctx(ctx);
+}
 
-       dprintk("RPC:       gss_destroy_cred \n");
+static void
+gss_free_ctx(struct gss_cl_ctx *ctx)
+{
+       call_rcu(&ctx->gc_rcu, gss_free_ctx_callback);
+}
 
-       if (cred->gc_ctx)
-               gss_put_ctx(cred->gc_ctx);
-       kfree(cred);
+static void
+gss_free_cred(struct gss_cred *gss_cred)
+{
+       dprintk("RPC:       gss_free_cred %p\n", gss_cred);
+       kfree(gss_cred);
+}
+
+static void
+gss_free_cred_callback(struct rcu_head *head)
+{
+       struct gss_cred *gss_cred = container_of(head, struct gss_cred, gc_base.cr_rcu);
+       gss_free_cred(gss_cred);
+}
+
+static void
+gss_destroy_cred(struct rpc_cred *cred)
+{
+       struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
+       struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
+       struct gss_cl_ctx *ctx = gss_cred->gc_ctx;
+
+       if (gss_destroying_context(cred))
+               return;
+       rcu_assign_pointer(gss_cred->gc_ctx, NULL);
+       call_rcu(&cred->cr_rcu, gss_free_cred_callback);
+       if (ctx)
+               gss_put_ctx(ctx);
+       kref_put(&gss_auth->kref, gss_free_callback);
 }
 
 /*
@@ -734,16 +808,14 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
        if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL)))
                goto out_err;
 
-       atomic_set(&cred->gc_count, 1);
-       cred->gc_uid = acred->uid;
+       rpcauth_init_cred(&cred->gc_base, acred, auth, &gss_credops);
        /*
         * Note: in order to force a call to call_refresh(), we deliberately
         * fail to flag the credential as RPCAUTH_CRED_UPTODATE.
         */
-       cred->gc_flags = 0;
-       cred->gc_base.cr_ops = &gss_credops;
-       cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
+       cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW;
        cred->gc_service = gss_auth->service;
+       kref_get(&gss_auth->kref);
        return &cred->gc_base;
 
 out_err:
@@ -774,7 +846,7 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
         * we don't really care if the credential has expired or not,
         * since the caller should be prepared to reinitialise it.
         */
-       if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW))
+       if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
                goto out;
        /* Don't match with creds that have expired. */
        if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
@@ -830,7 +902,7 @@ gss_marshal(struct rpc_task *task, __be32 *p)
        mic.data = (u8 *)(p + 1);
        maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
-               cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+               clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
        } else if (maj_stat != 0) {
                printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
                goto out_put_ctx;
@@ -855,6 +927,13 @@ gss_refresh(struct rpc_task *task)
        return 0;
 }
 
+/* Dummy refresh routine: used only when destroying the context */
+static int
+gss_refresh_null(struct rpc_task *task)
+{
+       return -EACCES;
+}
+
 static __be32 *
 gss_validate(struct rpc_task *task, __be32 *p)
 {
@@ -883,12 +962,15 @@ gss_validate(struct rpc_task *task, __be32 *p)
 
        maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
-               cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-       if (maj_stat)
+               clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+       if (maj_stat) {
+               dprintk("RPC: %5u gss_validate: gss_verify_mic returned"
+                               "error 0x%08x\n", task->tk_pid, maj_stat);
                goto out_bad;
+       }
        /* We leave it to unwrap to calculate au_rslack. For now we just
         * calculate the length of the verifier: */
-       task->tk_auth->au_verfsize = XDR_QUADLEN(len) + 2;
+       cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2;
        gss_put_ctx(ctx);
        dprintk("RPC: %5u gss_validate: gss_verify_mic succeeded.\n",
                        task->tk_pid);
@@ -917,7 +999,9 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
        *p++ = htonl(rqstp->rq_seqno);
 
+       lock_kernel();
        status = encode(rqstp, p, obj);
+       unlock_kernel();
        if (status)
                return status;
 
@@ -937,7 +1021,7 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
        status = -EIO; /* XXX? */
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
-               cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+               clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
        else if (maj_stat)
                return status;
        q = xdr_encode_opaque(p, NULL, mic.len);
@@ -1011,7 +1095,9 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
        *p++ = htonl(rqstp->rq_seqno);
 
+       lock_kernel();
        status = encode(rqstp, p, obj);
+       unlock_kernel();
        if (status)
                return status;
 
@@ -1036,7 +1122,7 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
         * done anyway, so it's safe to put the request on the wire: */
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
-               cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+               clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
        else if (maj_stat)
                return status;
 
@@ -1070,12 +1156,16 @@ gss_wrap_req(struct rpc_task *task,
                /* The spec seems a little ambiguous here, but I think that not
                 * wrapping context destruction requests makes the most sense.
                 */
+               lock_kernel();
                status = encode(rqstp, p, obj);
+               unlock_kernel();
                goto out;
        }
        switch (gss_cred->gc_service) {
                case RPC_GSS_SVC_NONE:
+                       lock_kernel();
                        status = encode(rqstp, p, obj);
+                       unlock_kernel();
                        break;
                case RPC_GSS_SVC_INTEGRITY:
                        status = gss_wrap_req_integ(cred, ctx, encode,
@@ -1123,7 +1213,7 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
 
        maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
-               cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+               clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
        if (maj_stat != GSS_S_COMPLETE)
                return status;
        return 0;
@@ -1148,7 +1238,7 @@ gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
 
        maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
-               cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+               clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
        if (maj_stat != GSS_S_COMPLETE)
                return status;
        if (ntohl(*(*p)++) != rqstp->rq_seqno)
@@ -1188,10 +1278,12 @@ gss_unwrap_resp(struct rpc_task *task,
                        break;
        }
        /* take into account extra slack for integrity and privacy cases: */
-       task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp)
+       cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp)
                                                + (savedlen - head->iov_len);
 out_decode:
+       lock_kernel();
        status = decode(rqstp, p, obj);
+       unlock_kernel();
 out:
        gss_put_ctx(ctx);
        dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid,
@@ -1199,7 +1291,7 @@ out:
        return status;
 }
 
-static struct rpc_authops authgss_ops = {
+static const struct rpc_authops authgss_ops = {
        .owner          = THIS_MODULE,
        .au_flavor      = RPC_AUTH_GSS,
 #ifdef RPC_DEBUG
@@ -1211,7 +1303,7 @@ static struct rpc_authops authgss_ops = {
        .crcreate       = gss_create_cred
 };
 
-static struct rpc_credops gss_credops = {
+static const struct rpc_credops gss_credops = {
        .cr_name        = "AUTH_GSS",
        .crdestroy      = gss_destroy_cred,
        .cr_init        = gss_cred_init,
@@ -1223,6 +1315,17 @@ static struct rpc_credops gss_credops = {
        .crunwrap_resp  = gss_unwrap_resp,
 };
 
+static const struct rpc_credops gss_nullops = {
+       .cr_name        = "AUTH_GSS",
+       .crdestroy      = gss_destroy_cred,
+       .crmatch        = gss_match,
+       .crmarshal      = gss_marshal,
+       .crrefresh      = gss_refresh_null,
+       .crvalidate     = gss_validate,
+       .crwrap_req     = gss_wrap_req,
+       .crunwrap_resp  = gss_unwrap_resp,
+};
+
 static struct rpc_pipe_ops gss_upcall_ops = {
        .upcall         = gss_pipe_upcall,
        .downcall       = gss_pipe_downcall,
index 7b194321705323441b28cb413632bcae23a3bc21..71b9daefdff3d046d9fcbd486af3eba60dc88e12 100644 (file)
@@ -201,7 +201,7 @@ gss_delete_sec_context_kerberos(void *internal_ctx) {
        kfree(kctx);
 }
 
-static struct gss_api_ops gss_kerberos_ops = {
+static const struct gss_api_ops gss_kerberos_ops = {
        .gss_import_sec_context = gss_import_sec_context_kerberos,
        .gss_get_mic            = gss_get_mic_kerberos,
        .gss_verify_mic         = gss_verify_mic_kerberos,
index 7e15aa68ae64c57800d4fef33f20bc1a9a80b33a..577d590e755f0cd292b73a971419bec77ecd2939 100644 (file)
@@ -202,7 +202,7 @@ gss_get_mic_spkm3(struct gss_ctx    *ctx,
        return err;
 }
 
-static struct gss_api_ops gss_spkm3_ops = {
+static const struct gss_api_ops gss_spkm3_ops = {
        .gss_import_sec_context = gss_import_sec_context_spkm3,
        .gss_get_mic            = gss_get_mic_spkm3,
        .gss_verify_mic         = gss_verify_mic_spkm3,
index 3df9fccab2f8b34c17b7d04208a0c46f3d9d4219..537d0e8589ddb598c9137eb97ccea1a870af04a6 100644 (file)
@@ -76,7 +76,7 @@ nul_marshal(struct rpc_task *task, __be32 *p)
 static int
 nul_refresh(struct rpc_task *task)
 {
-       task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
+       set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
        return 0;
 }
 
@@ -101,7 +101,7 @@ nul_validate(struct rpc_task *task, __be32 *p)
        return p;
 }
 
-struct rpc_authops authnull_ops = {
+const struct rpc_authops authnull_ops = {
        .owner          = THIS_MODULE,
        .au_flavor      = RPC_AUTH_NULL,
 #ifdef RPC_DEBUG
@@ -122,7 +122,7 @@ struct rpc_auth null_auth = {
 };
 
 static
-struct rpc_credops     null_credops = {
+const struct rpc_credops null_credops = {
        .cr_name        = "AUTH_NULL",
        .crdestroy      = nul_destroy_cred,
        .crmatch        = nul_match,
@@ -133,9 +133,11 @@ struct rpc_credops null_credops = {
 
 static
 struct rpc_cred null_cred = {
+       .cr_lru         = LIST_HEAD_INIT(null_cred.cr_lru),
+       .cr_auth        = &null_auth,
        .cr_ops         = &null_credops,
        .cr_count       = ATOMIC_INIT(1),
-       .cr_flags       = RPCAUTH_CRED_UPTODATE,
+       .cr_flags       = 1UL << RPCAUTH_CRED_UPTODATE,
 #ifdef RPC_DEBUG
        .cr_magic       = RPCAUTH_CRED_MAGIC,
 #endif
index 4e7733aee36e8f42dafa178cceabdfa028a3dbae..5ed91e5bcee4a9ce04e22a167450b6c612362970 100644 (file)
@@ -20,11 +20,6 @@ struct unx_cred {
        gid_t                   uc_gids[NFS_NGROUPS];
 };
 #define uc_uid                 uc_base.cr_uid
-#define uc_count               uc_base.cr_count
-#define uc_flags               uc_base.cr_flags
-#define uc_expire              uc_base.cr_expire
-
-#define UNX_CRED_EXPIRE                (60 * HZ)
 
 #define UNX_WRITESLACK         (21 + (UNX_MAXNODENAME >> 2))
 
@@ -34,15 +29,14 @@ struct unx_cred {
 
 static struct rpc_auth         unix_auth;
 static struct rpc_cred_cache   unix_cred_cache;
-static struct rpc_credops      unix_credops;
+static const struct rpc_credops        unix_credops;
 
 static struct rpc_auth *
 unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
 {
        dprintk("RPC:       creating UNIX authenticator for client %p\n",
                        clnt);
-       if (atomic_inc_return(&unix_auth.au_count) == 0)
-               unix_cred_cache.nextgc = jiffies + (unix_cred_cache.expire >> 1);
+       atomic_inc(&unix_auth.au_count);
        return &unix_auth;
 }
 
@@ -50,7 +44,7 @@ static void
 unx_destroy(struct rpc_auth *auth)
 {
        dprintk("RPC:       destroying UNIX authenticator %p\n", auth);
-       rpcauth_free_credcache(auth);
+       rpcauth_clear_credcache(auth->au_credcache);
 }
 
 /*
@@ -74,8 +68,8 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
        if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL)))
                return ERR_PTR(-ENOMEM);
 
-       atomic_set(&cred->uc_count, 1);
-       cred->uc_flags = RPCAUTH_CRED_UPTODATE;
+       rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops);
+       cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
        if (flags & RPCAUTH_LOOKUP_ROOTCREDS) {
                cred->uc_uid = 0;
                cred->uc_gid = 0;
@@ -85,22 +79,34 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
                if (groups > NFS_NGROUPS)
                        groups = NFS_NGROUPS;
 
-               cred->uc_uid = acred->uid;
                cred->uc_gid = acred->gid;
                for (i = 0; i < groups; i++)
                        cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
                if (i < NFS_NGROUPS)
                  cred->uc_gids[i] = NOGROUP;
        }
-       cred->uc_base.cr_ops = &unix_credops;
 
-       return (struct rpc_cred *) cred;
+       return &cred->uc_base;
+}
+
+static void
+unx_free_cred(struct unx_cred *unx_cred)
+{
+       dprintk("RPC:       unx_free_cred %p\n", unx_cred);
+       kfree(unx_cred);
+}
+
+static void
+unx_free_cred_callback(struct rcu_head *head)
+{
+       struct unx_cred *unx_cred = container_of(head, struct unx_cred, uc_base.cr_rcu);
+       unx_free_cred(unx_cred);
 }
 
 static void
 unx_destroy_cred(struct rpc_cred *cred)
 {
-       kfree(cred);
+       call_rcu(&cred->cr_rcu, unx_free_cred_callback);
 }
 
 /*
@@ -111,7 +117,7 @@ unx_destroy_cred(struct rpc_cred *cred)
 static int
 unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
 {
-       struct unx_cred *cred = (struct unx_cred *) rcred;
+       struct unx_cred *cred = container_of(rcred, struct unx_cred, uc_base);
        int             i;
 
        if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) {
@@ -142,7 +148,7 @@ static __be32 *
 unx_marshal(struct rpc_task *task, __be32 *p)
 {
        struct rpc_clnt *clnt = task->tk_client;
-       struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred;
+       struct unx_cred *cred = container_of(task->tk_msg.rpc_cred, struct unx_cred, uc_base);
        __be32          *base, *hold;
        int             i;
 
@@ -175,7 +181,7 @@ unx_marshal(struct rpc_task *task, __be32 *p)
 static int
 unx_refresh(struct rpc_task *task)
 {
-       task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
+       set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
        return 0;
 }
 
@@ -198,13 +204,18 @@ unx_validate(struct rpc_task *task, __be32 *p)
                printk("RPC: giant verf size: %u\n", size);
                return NULL;
        }
-       task->tk_auth->au_rslack = (size >> 2) + 2;
+       task->tk_msg.rpc_cred->cr_auth->au_rslack = (size >> 2) + 2;
        p += (size >> 2);
 
        return p;
 }
 
-struct rpc_authops     authunix_ops = {
+void __init rpc_init_authunix(void)
+{
+       spin_lock_init(&unix_cred_cache.lock);
+}
+
+const struct rpc_authops authunix_ops = {
        .owner          = THIS_MODULE,
        .au_flavor      = RPC_AUTH_UNIX,
 #ifdef RPC_DEBUG
@@ -218,7 +229,6 @@ struct rpc_authops  authunix_ops = {
 
 static
 struct rpc_cred_cache  unix_cred_cache = {
-       .expire         = UNX_CRED_EXPIRE,
 };
 
 static
@@ -232,7 +242,7 @@ struct rpc_auth             unix_auth = {
 };
 
 static
-struct rpc_credops     unix_credops = {
+const struct rpc_credops unix_credops = {
        .cr_name        = "AUTH_UNIX",
        .crdestroy      = unx_destroy_cred,
        .crmatch        = unx_match,
index d8fbee40a19cecf2a46200783a65c817e1c97504..52429b1ffcc1d8d33bf7cf116bab5bfa0ceb052c 100644 (file)
        dprintk("RPC: %5u %s (status %d)\n", t->tk_pid,         \
                        __FUNCTION__, t->tk_status)
 
+/*
+ * All RPC clients are linked into this list
+ */
+static LIST_HEAD(all_clients);
+static DEFINE_SPINLOCK(rpc_client_lock);
+
 static DECLARE_WAIT_QUEUE_HEAD(destroy_wait);
 
 
@@ -66,6 +72,21 @@ static void  call_connect_status(struct rpc_task *task);
 static __be32 *        call_header(struct rpc_task *task);
 static __be32 *        call_verify(struct rpc_task *task);
 
+static int     rpc_ping(struct rpc_clnt *clnt, int flags);
+
+static void rpc_register_client(struct rpc_clnt *clnt)
+{
+       spin_lock(&rpc_client_lock);
+       list_add(&clnt->cl_clients, &all_clients);
+       spin_unlock(&rpc_client_lock);
+}
+
+static void rpc_unregister_client(struct rpc_clnt *clnt)
+{
+       spin_lock(&rpc_client_lock);
+       list_del(&clnt->cl_clients);
+       spin_unlock(&rpc_client_lock);
+}
 
 static int
 rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
@@ -111,6 +132,9 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
        dprintk("RPC:       creating %s client for %s (xprt %p)\n",
                        program->name, servname, xprt);
 
+       err = rpciod_up();
+       if (err)
+               goto out_no_rpciod;
        err = -EINVAL;
        if (!xprt)
                goto out_no_xprt;
@@ -121,8 +145,6 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
        clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
        if (!clnt)
                goto out_err;
-       atomic_set(&clnt->cl_users, 0);
-       atomic_set(&clnt->cl_count, 1);
        clnt->cl_parent = clnt;
 
        clnt->cl_server = clnt->cl_inline_name;
@@ -148,6 +170,8 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
        if (clnt->cl_metrics == NULL)
                goto out_no_stats;
        clnt->cl_program  = program;
+       INIT_LIST_HEAD(&clnt->cl_tasks);
+       spin_lock_init(&clnt->cl_lock);
 
        if (!xprt_bound(clnt->cl_xprt))
                clnt->cl_autobind = 1;
@@ -155,6 +179,8 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
        clnt->cl_rtt = &clnt->cl_rtt_default;
        rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval);
 
+       kref_init(&clnt->cl_kref);
+
        err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
        if (err < 0)
                goto out_no_path;
@@ -172,6 +198,7 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
        if (clnt->cl_nodelen > UNX_MAXNODENAME)
                clnt->cl_nodelen = UNX_MAXNODENAME;
        memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen);
+       rpc_register_client(clnt);
        return clnt;
 
 out_no_auth:
@@ -188,6 +215,8 @@ out_no_stats:
 out_err:
        xprt_put(xprt);
 out_no_xprt:
+       rpciod_down();
+out_no_rpciod:
        return ERR_PTR(err);
 }
 
@@ -205,12 +234,31 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
 {
        struct rpc_xprt *xprt;
        struct rpc_clnt *clnt;
+       struct rpc_xprtsock_create xprtargs = {
+               .proto = args->protocol,
+               .srcaddr = args->saddress,
+               .dstaddr = args->address,
+               .addrlen = args->addrsize,
+               .timeout = args->timeout
+       };
+       char servername[20];
 
-       xprt = xprt_create_transport(args->protocol, args->address,
-                                       args->addrsize, args->timeout);
+       xprt = xprt_create_transport(&xprtargs);
        if (IS_ERR(xprt))
                return (struct rpc_clnt *)xprt;
 
+       /*
+        * If the caller chooses not to specify a hostname, whip
+        * up a string representation of the passed-in address.
+        */
+       if (args->servername == NULL) {
+               struct sockaddr_in *addr =
+                                       (struct sockaddr_in *) &args->address;
+               snprintf(servername, sizeof(servername), NIPQUAD_FMT,
+                       NIPQUAD(addr->sin_addr.s_addr));
+               args->servername = servername;
+       }
+
        /*
         * By default, kernel RPC client connects from a reserved port.
         * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters,
@@ -245,8 +293,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
                clnt->cl_intr = 1;
        if (args->flags & RPC_CLNT_CREATE_AUTOBIND)
                clnt->cl_autobind = 1;
-       if (args->flags & RPC_CLNT_CREATE_ONESHOT)
-               clnt->cl_oneshot = 1;
        if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
                clnt->cl_discrtry = 1;
 
@@ -268,24 +314,25 @@ rpc_clone_client(struct rpc_clnt *clnt)
        new = kmemdup(clnt, sizeof(*new), GFP_KERNEL);
        if (!new)
                goto out_no_clnt;
-       atomic_set(&new->cl_count, 1);
-       atomic_set(&new->cl_users, 0);
+       new->cl_parent = clnt;
+       /* Turn off autobind on clones */
+       new->cl_autobind = 0;
+       INIT_LIST_HEAD(&new->cl_tasks);
+       spin_lock_init(&new->cl_lock);
+       rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
        new->cl_metrics = rpc_alloc_iostats(clnt);
        if (new->cl_metrics == NULL)
                goto out_no_stats;
+       kref_init(&new->cl_kref);
        err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
        if (err != 0)
                goto out_no_path;
-       new->cl_parent = clnt;
-       atomic_inc(&clnt->cl_count);
-       new->cl_xprt = xprt_get(clnt->cl_xprt);
-       /* Turn off autobind on clones */
-       new->cl_autobind = 0;
-       new->cl_oneshot = 0;
-       new->cl_dead = 0;
-       rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
        if (new->cl_auth)
                atomic_inc(&new->cl_auth->au_count);
+       xprt_get(clnt->cl_xprt);
+       kref_get(&clnt->cl_kref);
+       rpc_register_client(new);
+       rpciod_up();
        return new;
 out_no_path:
        rpc_free_iostats(new->cl_metrics);
@@ -298,86 +345,86 @@ out_no_clnt:
 
 /*
  * Properly shut down an RPC client, terminating all outstanding
- * requests. Note that we must be certain that cl_oneshot and
- * cl_dead are cleared, or else the client would be destroyed
- * when the last task releases it.
+ * requests.
  */
-int
-rpc_shutdown_client(struct rpc_clnt *clnt)
+void rpc_shutdown_client(struct rpc_clnt *clnt)
 {
-       dprintk("RPC:       shutting down %s client for %s, tasks=%d\n",
-                       clnt->cl_protname, clnt->cl_server,
-                       atomic_read(&clnt->cl_users));
-
-       while (atomic_read(&clnt->cl_users) > 0) {
-               /* Don't let rpc_release_client destroy us */
-               clnt->cl_oneshot = 0;
-               clnt->cl_dead = 0;
+       dprintk("RPC:       shutting down %s client for %s\n",
+                       clnt->cl_protname, clnt->cl_server);
+
+       while (!list_empty(&clnt->cl_tasks)) {
                rpc_killall_tasks(clnt);
                wait_event_timeout(destroy_wait,
-                       !atomic_read(&clnt->cl_users), 1*HZ);
-       }
-
-       if (atomic_read(&clnt->cl_users) < 0) {
-               printk(KERN_ERR "RPC: rpc_shutdown_client clnt %p tasks=%d\n",
-                               clnt, atomic_read(&clnt->cl_users));
-#ifdef RPC_DEBUG
-               rpc_show_tasks();
-#endif
-               BUG();
+                       list_empty(&clnt->cl_tasks), 1*HZ);
        }
 
-       return rpc_destroy_client(clnt);
+       rpc_release_client(clnt);
 }
 
 /*
- * Delete an RPC client
+ * Free an RPC client
  */
-int
-rpc_destroy_client(struct rpc_clnt *clnt)
+static void
+rpc_free_client(struct kref *kref)
 {
-       if (!atomic_dec_and_test(&clnt->cl_count))
-               return 1;
-       BUG_ON(atomic_read(&clnt->cl_users) != 0);
+       struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
 
        dprintk("RPC:       destroying %s client for %s\n",
                        clnt->cl_protname, clnt->cl_server);
-       if (clnt->cl_auth) {
-               rpcauth_destroy(clnt->cl_auth);
-               clnt->cl_auth = NULL;
-       }
        if (!IS_ERR(clnt->cl_dentry)) {
                rpc_rmdir(clnt->cl_dentry);
                rpc_put_mount();
        }
        if (clnt->cl_parent != clnt) {
-               rpc_destroy_client(clnt->cl_parent);
+               rpc_release_client(clnt->cl_parent);
                goto out_free;
        }
        if (clnt->cl_server != clnt->cl_inline_name)
                kfree(clnt->cl_server);
 out_free:
+       rpc_unregister_client(clnt);
        rpc_free_iostats(clnt->cl_metrics);
        clnt->cl_metrics = NULL;
        xprt_put(clnt->cl_xprt);
+       rpciod_down();
        kfree(clnt);
-       return 0;
 }
 
 /*
- * Release an RPC client
+ * Free an RPC client
+ */
+static void
+rpc_free_auth(struct kref *kref)
+{
+       struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
+
+       if (clnt->cl_auth == NULL) {
+               rpc_free_client(kref);
+               return;
+       }
+
+       /*
+        * Note: RPCSEC_GSS may need to send NULL RPC calls in order to
+        *       release remaining GSS contexts. This mechanism ensures
+        *       that it can do so safely.
+        */
+       kref_init(kref);
+       rpcauth_release(clnt->cl_auth);
+       clnt->cl_auth = NULL;
+       kref_put(kref, rpc_free_client);
+}
+
+/*
+ * Release reference to the RPC client
  */
 void
 rpc_release_client(struct rpc_clnt *clnt)
 {
-       dprintk("RPC:       rpc_release_client(%p, %d)\n",
-                       clnt, atomic_read(&clnt->cl_users));
+       dprintk("RPC:       rpc_release_client(%p)\n", clnt);
 
-       if (!atomic_dec_and_test(&clnt->cl_users))
-               return;
-       wake_up(&destroy_wait);
-       if (clnt->cl_oneshot || clnt->cl_dead)
-               rpc_destroy_client(clnt);
+       if (list_empty(&clnt->cl_tasks))
+               wake_up(&destroy_wait);
+       kref_put(&clnt->cl_kref, rpc_free_auth);
 }
 
 /**
@@ -468,82 +515,96 @@ void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset)
        rpc_restore_sigmask(oldset);
 }
 
-/*
- * New rpc_call implementation
+static
+struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
+               struct rpc_message *msg,
+               int flags,
+               const struct rpc_call_ops *ops,
+               void *data)
+{
+       struct rpc_task *task, *ret;
+       sigset_t oldset;
+
+       task = rpc_new_task(clnt, flags, ops, data);
+       if (task == NULL) {
+               rpc_release_calldata(ops, data);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */
+       rpc_task_sigmask(task, &oldset);
+       if (msg != NULL) {
+               rpc_call_setup(task, msg, 0);
+               if (task->tk_status != 0) {
+                       ret = ERR_PTR(task->tk_status);
+                       rpc_put_task(task);
+                       goto out;
+               }
+       }
+       atomic_inc(&task->tk_count);
+       rpc_execute(task);
+       ret = task;
+out:
+       rpc_restore_sigmask(&oldset);
+       return ret;
+}
+
+/**
+ * rpc_call_sync - Perform a synchronous RPC call
+ * @clnt: pointer to RPC client
+ * @msg: RPC call parameters
+ * @flags: RPC call flags
  */
 int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 {
        struct rpc_task *task;
-       sigset_t        oldset;
-       int             status;
-
-       /* If this client is slain all further I/O fails */
-       if (clnt->cl_dead)
-               return -EIO;
+       int status;
 
        BUG_ON(flags & RPC_TASK_ASYNC);
 
-       task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL);
-       if (task == NULL)
-               return -ENOMEM;
-
-       /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */
-       rpc_task_sigmask(task, &oldset);
-
-       /* Set up the call info struct and execute the task */
-       rpc_call_setup(task, msg, 0);
-       if (task->tk_status == 0) {
-               atomic_inc(&task->tk_count);
-               rpc_execute(task);
-       }
+       task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
        status = task->tk_status;
        rpc_put_task(task);
-       rpc_restore_sigmask(&oldset);
        return status;
 }
 
-/*
- * New rpc_call implementation
+/**
+ * rpc_call_async - Perform an asynchronous RPC call
+ * @clnt: pointer to RPC client
+ * @msg: RPC call parameters
+ * @flags: RPC call flags
+ * @ops: RPC call ops
+ * @data: user call data
  */
 int
 rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
               const struct rpc_call_ops *tk_ops, void *data)
 {
        struct rpc_task *task;
-       sigset_t        oldset;
-       int             status;
-
-       /* If this client is slain all further I/O fails */
-       status = -EIO;
-       if (clnt->cl_dead)
-               goto out_release;
-
-       flags |= RPC_TASK_ASYNC;
-
-       /* Create/initialize a new RPC task */
-       status = -ENOMEM;
-       if (!(task = rpc_new_task(clnt, flags, tk_ops, data)))
-               goto out_release;
-
-       /* Mask signals on GSS_AUTH upcalls */
-       rpc_task_sigmask(task, &oldset);
 
-       rpc_call_setup(task, msg, 0);
-
-       /* Set up the call info struct and execute the task */
-       status = task->tk_status;
-       if (status == 0)
-               rpc_execute(task);
-       else
-               rpc_put_task(task);
-
-       rpc_restore_sigmask(&oldset);
-       return status;
-out_release:
-       rpc_release_calldata(tk_ops, data);
-       return status;
+       task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       rpc_put_task(task);
+       return 0;
 }
 
+/**
+ * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
+ * @clnt: pointer to RPC client
+ * @flags: RPC flags
+ * @ops: RPC call ops
+ * @data: user call data
+ */
+struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
+                                       const struct rpc_call_ops *tk_ops,
+                                       void *data)
+{
+       return rpc_do_run_task(clnt, NULL, flags, tk_ops, data);
+}
+EXPORT_SYMBOL(rpc_run_task);
 
 void
 rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
@@ -745,7 +806,7 @@ call_reserveresult(struct rpc_task *task)
 static void
 call_allocate(struct rpc_task *task)
 {
-       unsigned int slack = task->tk_auth->au_cslack;
+       unsigned int slack = task->tk_msg.rpc_cred->cr_auth->au_cslack;
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = task->tk_xprt;
        struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
@@ -843,10 +904,8 @@ call_encode(struct rpc_task *task)
        if (encode == NULL)
                return;
 
-       lock_kernel();
        task->tk_status = rpcauth_wrap_req(task, encode, req, p,
                        task->tk_msg.rpc_argp);
-       unlock_kernel();
        if (task->tk_status == -ENOMEM) {
                /* XXX: Is this sane? */
                rpc_delay(task, 3*HZ);
@@ -1177,10 +1236,8 @@ call_decode(struct rpc_task *task)
        task->tk_action = rpc_exit_task;
 
        if (decode) {
-               lock_kernel();
                task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
                                                      task->tk_msg.rpc_resp);
-               unlock_kernel();
        }
        dprintk("RPC: %5u call_decode result %d\n", task->tk_pid,
                        task->tk_status);
@@ -1273,9 +1330,9 @@ call_verify(struct rpc_task *task)
                 * - if it isn't pointer subtraction in the NFS client may give
                 *   undefined results
                 */
-               printk(KERN_WARNING
-                      "call_verify: XDR representation not a multiple of"
-                      " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len);
+               dprintk("RPC: %5u %s: XDR representation not a multiple of"
+                      " 4 bytes: 0x%x\n", task->tk_pid, __FUNCTION__,
+                      task->tk_rqstp->rq_rcv_buf.len);
                goto out_eio;
        }
        if ((len -= 3) < 0)
@@ -1283,7 +1340,8 @@ call_verify(struct rpc_task *task)
        p += 1; /* skip XID */
 
        if ((n = ntohl(*p++)) != RPC_REPLY) {
-               printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n);
+               dprintk("RPC: %5u %s: not an RPC reply: %x\n",
+                               task->tk_pid, __FUNCTION__, n);
                goto out_garbage;
        }
        if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
@@ -1334,7 +1392,8 @@ call_verify(struct rpc_task *task)
                               "authentication.\n", task->tk_client->cl_server);
                        break;
                default:
-                       printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n);
+                       dprintk("RPC: %5u %s: unknown auth error: %x\n",
+                                       task->tk_pid, __FUNCTION__, n);
                        error = -EIO;
                }
                dprintk("RPC: %5u %s: call rejected %d\n",
@@ -1342,7 +1401,8 @@ call_verify(struct rpc_task *task)
                goto out_err;
        }
        if (!(p = rpcauth_checkverf(task, p))) {
-               printk(KERN_WARNING "call_verify: auth check failed\n");
+               dprintk("RPC: %5u %s: auth check failed\n",
+                               task->tk_pid, __FUNCTION__);
                goto out_garbage;               /* bad verifier, retry */
        }
        len = p - (__be32 *)iov->iov_base - 1;
@@ -1381,7 +1441,8 @@ call_verify(struct rpc_task *task)
                                task->tk_pid, __FUNCTION__);
                break;                  /* retry */
        default:
-               printk(KERN_WARNING "call_verify: server accept status: %x\n", n);
+               dprintk("RPC: %5u %s: server accept status: %x\n",
+                               task->tk_pid, __FUNCTION__, n);
                /* Also retry */
        }
 
@@ -1395,14 +1456,16 @@ out_garbage:
 out_retry:
                return ERR_PTR(-EAGAIN);
        }
-       printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__);
 out_eio:
        error = -EIO;
 out_err:
        rpc_exit(task, error);
+       dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid,
+                       __FUNCTION__, error);
        return ERR_PTR(error);
 out_overflow:
-       printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__);
+       dprintk("RPC: %5u %s: server reply was truncated.\n", task->tk_pid,
+                       __FUNCTION__);
        goto out_garbage;
 }
 
@@ -1421,7 +1484,7 @@ static struct rpc_procinfo rpcproc_null = {
        .p_decode = rpcproc_decode_null,
 };
 
-int rpc_ping(struct rpc_clnt *clnt, int flags)
+static int rpc_ping(struct rpc_clnt *clnt, int flags)
 {
        struct rpc_message msg = {
                .rpc_proc = &rpcproc_null,
@@ -1432,3 +1495,51 @@ int rpc_ping(struct rpc_clnt *clnt, int flags)
        put_rpccred(msg.rpc_cred);
        return err;
 }
+
+struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags)
+{
+       struct rpc_message msg = {
+               .rpc_proc = &rpcproc_null,
+               .rpc_cred = cred,
+       };
+       return rpc_do_run_task(clnt, &msg, flags, &rpc_default_ops, NULL);
+}
+EXPORT_SYMBOL(rpc_call_null);
+
+#ifdef RPC_DEBUG
+void rpc_show_tasks(void)
+{
+       struct rpc_clnt *clnt;
+       struct rpc_task *t;
+
+       spin_lock(&rpc_client_lock);
+       if (list_empty(&all_clients))
+               goto out;
+       printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
+               "-rpcwait -action- ---ops--\n");
+       list_for_each_entry(clnt, &all_clients, cl_clients) {
+               if (list_empty(&clnt->cl_tasks))
+                       continue;
+               spin_lock(&clnt->cl_lock);
+               list_for_each_entry(t, &clnt->cl_tasks, tk_task) {
+                       const char *rpc_waitq = "none";
+
+                       if (RPC_IS_QUEUED(t))
+                               rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
+
+                       printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
+                               t->tk_pid,
+                               (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
+                               t->tk_flags, t->tk_status,
+                               t->tk_client,
+                               (t->tk_client ? t->tk_client->cl_prog : 0),
+                               t->tk_rqstp, t->tk_timeout,
+                               rpc_waitq,
+                               t->tk_action, t->tk_ops);
+               }
+               spin_unlock(&clnt->cl_lock);
+       }
+out:
+       spin_unlock(&rpc_client_lock);
+}
+#endif
index 5887457dc936d06244404183627fa989f70d24fe..e787b6a43eeeaccaeec0f9c73cb21c230b4d4826 100644 (file)
@@ -344,7 +344,7 @@ rpc_info_open(struct inode *inode, struct file *file)
                mutex_lock(&inode->i_mutex);
                clnt = RPC_I(inode)->private;
                if (clnt) {
-                       atomic_inc(&clnt->cl_users);
+                       kref_get(&clnt->cl_kref);
                        m->private = clnt;
                } else {
                        single_release(inode, file);
@@ -448,6 +448,15 @@ void rpc_put_mount(void)
        simple_release_fs(&rpc_mount, &rpc_mount_count);
 }
 
+static int rpc_delete_dentry(struct dentry *dentry)
+{
+       return 1;
+}
+
+static struct dentry_operations rpc_dentry_operations = {
+       .d_delete = rpc_delete_dentry,
+};
+
 static int
 rpc_lookup_parent(char *path, struct nameidata *nd)
 {
@@ -506,7 +515,7 @@ rpc_get_inode(struct super_block *sb, int mode)
  * FIXME: This probably has races.
  */
 static void
-rpc_depopulate(struct dentry *parent)
+rpc_depopulate(struct dentry *parent, int start, int eof)
 {
        struct inode *dir = parent->d_inode;
        struct list_head *pos, *next;
@@ -518,6 +527,10 @@ repeat:
        spin_lock(&dcache_lock);
        list_for_each_safe(pos, next, &parent->d_subdirs) {
                dentry = list_entry(pos, struct dentry, d_u.d_child);
+               if (!dentry->d_inode ||
+                               dentry->d_inode->i_ino < start ||
+                               dentry->d_inode->i_ino >= eof)
+                       continue;
                spin_lock(&dentry->d_lock);
                if (!d_unhashed(dentry)) {
                        dget_locked(dentry);
@@ -533,11 +546,11 @@ repeat:
        if (n) {
                do {
                        dentry = dvec[--n];
-                       if (dentry->d_inode) {
-                               rpc_close_pipes(dentry->d_inode);
+                       if (S_ISREG(dentry->d_inode->i_mode))
                                simple_unlink(dir, dentry);
-                       }
-                       inode_dir_notify(dir, DN_DELETE);
+                       else if (S_ISDIR(dentry->d_inode->i_mode))
+                               simple_rmdir(dir, dentry);
+                       d_delete(dentry);
                        dput(dentry);
                } while (n);
                goto repeat;
@@ -560,6 +573,7 @@ rpc_populate(struct dentry *parent,
                dentry = d_alloc_name(parent, files[i].name);
                if (!dentry)
                        goto out_bad;
+               dentry->d_op = &rpc_dentry_operations;
                mode = files[i].mode;
                inode = rpc_get_inode(dir->i_sb, mode);
                if (!inode) {
@@ -607,21 +621,14 @@ static int
 __rpc_rmdir(struct inode *dir, struct dentry *dentry)
 {
        int error;
-
-       shrink_dcache_parent(dentry);
-       if (d_unhashed(dentry))
-               return 0;
-       if ((error = simple_rmdir(dir, dentry)) != 0)
-               return error;
-       if (!error) {
-               inode_dir_notify(dir, DN_DELETE);
-               d_drop(dentry);
-       }
-       return 0;
+       error = simple_rmdir(dir, dentry);
+       if (!error)
+               d_delete(dentry);
+       return error;
 }
 
 static struct dentry *
-rpc_lookup_create(struct dentry *parent, const char *name, int len)
+rpc_lookup_create(struct dentry *parent, const char *name, int len, int exclusive)
 {
        struct inode *dir = parent->d_inode;
        struct dentry *dentry;
@@ -630,7 +637,9 @@ rpc_lookup_create(struct dentry *parent, const char *name, int len)
        dentry = lookup_one_len(name, parent, len);
        if (IS_ERR(dentry))
                goto out_err;
-       if (dentry->d_inode) {
+       if (!dentry->d_inode)
+               dentry->d_op = &rpc_dentry_operations;
+       else if (exclusive) {
                dput(dentry);
                dentry = ERR_PTR(-EEXIST);
                goto out_err;
@@ -649,7 +658,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd)
 
        if ((error = rpc_lookup_parent(path, nd)) != 0)
                return ERR_PTR(error);
-       dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len);
+       dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len, 1);
        if (IS_ERR(dentry))
                rpc_release_path(nd);
        return dentry;
@@ -681,7 +690,7 @@ out:
        rpc_release_path(&nd);
        return dentry;
 err_depopulate:
-       rpc_depopulate(dentry);
+       rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
        __rpc_rmdir(dir, dentry);
 err_dput:
        dput(dentry);
@@ -701,7 +710,7 @@ rpc_rmdir(struct dentry *dentry)
        parent = dget_parent(dentry);
        dir = parent->d_inode;
        mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
-       rpc_depopulate(dentry);
+       rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
        error = __rpc_rmdir(dir, dentry);
        dput(dentry);
        mutex_unlock(&dir->i_mutex);
@@ -716,10 +725,21 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi
        struct inode *dir, *inode;
        struct rpc_inode *rpci;
 
-       dentry = rpc_lookup_create(parent, name, strlen(name));
+       dentry = rpc_lookup_create(parent, name, strlen(name), 0);
        if (IS_ERR(dentry))
                return dentry;
        dir = parent->d_inode;
+       if (dentry->d_inode) {
+               rpci = RPC_I(dentry->d_inode);
+               if (rpci->private != private ||
+                               rpci->ops != ops ||
+                               rpci->flags != flags) {
+                       dput (dentry);
+                       dentry = ERR_PTR(-EBUSY);
+               }
+               rpci->nkern_readwriters++;
+               goto out;
+       }
        inode = rpc_get_inode(dir->i_sb, S_IFIFO | S_IRUSR | S_IWUSR);
        if (!inode)
                goto err_dput;
@@ -730,6 +750,7 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi
        rpci->private = private;
        rpci->flags = flags;
        rpci->ops = ops;
+       rpci->nkern_readwriters = 1;
        inode_dir_notify(dir, DN_CREATE);
        dget(dentry);
 out:
@@ -754,13 +775,11 @@ rpc_unlink(struct dentry *dentry)
        parent = dget_parent(dentry);
        dir = parent->d_inode;
        mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
-       if (!d_unhashed(dentry)) {
-               d_drop(dentry);
-               if (dentry->d_inode) {
-                       rpc_close_pipes(dentry->d_inode);
-                       error = simple_unlink(dir, dentry);
-               }
-               inode_dir_notify(dir, DN_DELETE);
+       if (--RPC_I(dentry->d_inode)->nkern_readwriters == 0) {
+               rpc_close_pipes(dentry->d_inode);
+               error = simple_unlink(dir, dentry);
+               if (!error)
+                       d_delete(dentry);
        }
        dput(dentry);
        mutex_unlock(&dir->i_mutex);
@@ -833,6 +852,7 @@ init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
        rpci->nreaders = 0;
        rpci->nwriters = 0;
        INIT_LIST_HEAD(&rpci->in_upcall);
+       INIT_LIST_HEAD(&rpci->in_downcall);
        INIT_LIST_HEAD(&rpci->pipe);
        rpci->pipelen = 0;
        init_waitqueue_head(&rpci->waitq);
index 6c7aa8a1f0c65f41ecdab07e61d2958c08569f48..d1740dbab991e98747593ebd16618a7245384567 100644 (file)
@@ -12,6 +12,8 @@
  *  Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
  */
 
+#include <linux/module.h>
+
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/kernel.h>
@@ -184,8 +186,8 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
                .program        = &rpcb_program,
                .version        = version,
                .authflavor     = RPC_AUTH_UNIX,
-               .flags          = (RPC_CLNT_CREATE_ONESHOT |
-                                  RPC_CLNT_CREATE_NOPING),
+               .flags          = (RPC_CLNT_CREATE_NOPING |
+                                  RPC_CLNT_CREATE_INTR),
        };
 
        ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
@@ -238,6 +240,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
 
        error = rpc_call_sync(rpcb_clnt, &msg, 0);
 
+       rpc_shutdown_client(rpcb_clnt);
        if (error < 0)
                printk(KERN_WARNING "RPC: failed to contact local rpcbind "
                                "server (errno %d).\n", -error);
@@ -246,21 +249,20 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
        return error;
 }
 
-#ifdef CONFIG_ROOT_NFS
 /**
- * rpcb_getport_external - obtain the port for an RPC service on a given host
+ * rpcb_getport_sync - obtain the port for an RPC service on a given host
  * @sin: address of remote peer
  * @prog: RPC program number to bind
  * @vers: RPC version number to bind
  * @prot: transport protocol to use to make this request
  *
  * Called from outside the RPC client in a synchronous task context.
+ * Uses default timeout parameters specified by underlying transport.
  *
- * For now, this supports only version 2 queries, but is used only by
- * mount_clnt for NFS_ROOT.
+ * XXX: Needs to support IPv6, and rpcbind versions 3 and 4
  */
-int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
-                               __u32 vers, int prot)
+int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
+                     __u32 vers, int prot)
 {
        struct rpcbind_args map = {
                .r_prog         = prog,
@@ -277,15 +279,16 @@ int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
        char hostname[40];
        int status;
 
-       dprintk("RPC:       rpcb_getport_external(%u.%u.%u.%u, %u, %u, %d)\n",
-                       NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
+       dprintk("RPC:       %s(" NIPQUAD_FMT ", %u, %u, %d)\n",
+               __FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
 
-       sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
+       sprintf(hostname, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
        rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0);
        if (IS_ERR(rpcb_clnt))
                return PTR_ERR(rpcb_clnt);
 
        status = rpc_call_sync(rpcb_clnt, &msg, 0);
+       rpc_shutdown_client(rpcb_clnt);
 
        if (status >= 0) {
                if (map.r_port != 0)
@@ -294,16 +297,16 @@ int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
        }
        return status;
 }
-#endif
+EXPORT_SYMBOL_GPL(rpcb_getport_sync);
 
 /**
- * rpcb_getport - obtain the port for a given RPC service on a given host
+ * rpcb_getport_async - obtain the port for a given RPC service on a given host
  * @task: task that is waiting for portmapper request
  *
  * This one can be called for an ongoing RPC request, and can be used in
  * an async (rpciod) context.
  */
-void rpcb_getport(struct rpc_task *task)
+void rpcb_getport_async(struct rpc_task *task)
 {
        struct rpc_clnt *clnt = task->tk_client;
        int bind_version;
@@ -314,17 +317,17 @@ void rpcb_getport(struct rpc_task *task)
        struct sockaddr addr;
        int status;
 
-       dprintk("RPC: %5u rpcb_getport(%s, %u, %u, %d)\n",
-                       task->tk_pid, clnt->cl_server,
-                       clnt->cl_prog, clnt->cl_vers, xprt->prot);
+       dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
+               task->tk_pid, __FUNCTION__,
+               clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
 
        /* Autobind on cloned rpc clients is discouraged */
        BUG_ON(clnt->cl_parent != clnt);
 
        if (xprt_test_and_set_binding(xprt)) {
                status = -EACCES;               /* tell caller to check again */
-               dprintk("RPC: %5u rpcb_getport waiting for another binder\n",
-                               task->tk_pid);
+               dprintk("RPC: %5u %s: waiting for another binder\n",
+                       task->tk_pid, __FUNCTION__);
                goto bailout_nowake;
        }
 
@@ -335,27 +338,28 @@ void rpcb_getport(struct rpc_task *task)
        /* Someone else may have bound if we slept */
        if (xprt_bound(xprt)) {
                status = 0;
-               dprintk("RPC: %5u rpcb_getport already bound\n", task->tk_pid);
+               dprintk("RPC: %5u %s: already bound\n",
+                       task->tk_pid, __FUNCTION__);
                goto bailout_nofree;
        }
 
        if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) {
                xprt->bind_index = 0;
                status = -EACCES;       /* tell caller to try again later */
-               dprintk("RPC: %5u rpcb_getport no more getport versions "
-                               "available\n", task->tk_pid);
+               dprintk("RPC: %5u %s: no more getport versions available\n",
+                       task->tk_pid, __FUNCTION__);
                goto bailout_nofree;
        }
        bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
 
-       dprintk("RPC: %5u rpcb_getport trying rpcbind version %u\n",
-                       task->tk_pid, bind_version);
+       dprintk("RPC: %5u %s: trying rpcbind version %u\n",
+               task->tk_pid, __FUNCTION__, bind_version);
 
        map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC);
        if (!map) {
                status = -ENOMEM;
-               dprintk("RPC: %5u rpcb_getport no memory available\n",
-                               task->tk_pid);
+               dprintk("RPC: %5u %s: no memory available\n",
+                       task->tk_pid, __FUNCTION__);
                goto bailout_nofree;
        }
        map->r_prog = clnt->cl_prog;
@@ -373,16 +377,17 @@ void rpcb_getport(struct rpc_task *task)
        rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0);
        if (IS_ERR(rpcb_clnt)) {
                status = PTR_ERR(rpcb_clnt);
-               dprintk("RPC: %5u rpcb_getport rpcb_create failed, error %ld\n",
-                               task->tk_pid, PTR_ERR(rpcb_clnt));
+               dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
+                       task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt));
                goto bailout;
        }
 
        child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map);
+       rpc_release_client(rpcb_clnt);
        if (IS_ERR(child)) {
                status = -EIO;
-               dprintk("RPC: %5u rpcb_getport rpc_run_task failed\n",
-                               task->tk_pid);
+               dprintk("RPC: %5u %s: rpc_run_task failed\n",
+                       task->tk_pid, __FUNCTION__);
                goto bailout_nofree;
        }
        rpc_put_task(child);
index 944d75396fb3a39448b20c4036932917c631dd46..2ac43c41c3a9889664a1c36b5072e1690ce0fea2 100644 (file)
@@ -25,7 +25,6 @@
 #ifdef RPC_DEBUG
 #define RPCDBG_FACILITY                RPCDBG_SCHED
 #define RPC_TASK_MAGIC_ID      0xf00baa
-static int                     rpc_task_id;
 #endif
 
 /*
@@ -40,7 +39,6 @@ static mempool_t      *rpc_task_mempool __read_mostly;
 static mempool_t       *rpc_buffer_mempool __read_mostly;
 
 static void                    __rpc_default_timer(struct rpc_task *task);
-static void                    rpciod_killall(void);
 static void                    rpc_async_schedule(struct work_struct *);
 static void                     rpc_release_task(struct rpc_task *task);
 
@@ -49,23 +47,13 @@ static void                  rpc_release_task(struct rpc_task *task);
  */
 static RPC_WAITQ(delay_queue, "delayq");
 
-/*
- * All RPC tasks are linked into this list
- */
-static LIST_HEAD(all_tasks);
-
 /*
  * rpciod-related stuff
  */
 static DEFINE_MUTEX(rpciod_mutex);
-static unsigned int            rpciod_users;
+static atomic_t rpciod_users = ATOMIC_INIT(0);
 struct workqueue_struct *rpciod_workqueue;
 
-/*
- * Spinlock for other critical sections of code.
- */
-static DEFINE_SPINLOCK(rpc_sched_lock);
-
 /*
  * Disable the timer for a given RPC task. Should be called with
  * queue->lock and bh_disabled in order to avoid races within
@@ -267,18 +255,33 @@ static int rpc_wait_bit_interruptible(void *word)
        return 0;
 }
 
+#ifdef RPC_DEBUG
+static void rpc_task_set_debuginfo(struct rpc_task *task)
+{
+       static atomic_t rpc_pid;
+
+       task->tk_magic = RPC_TASK_MAGIC_ID;
+       task->tk_pid = atomic_inc_return(&rpc_pid);
+}
+#else
+static inline void rpc_task_set_debuginfo(struct rpc_task *task)
+{
+}
+#endif
+
 static void rpc_set_active(struct rpc_task *task)
 {
+       struct rpc_clnt *clnt;
        if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0)
                return;
-       spin_lock(&rpc_sched_lock);
-#ifdef RPC_DEBUG
-       task->tk_magic = RPC_TASK_MAGIC_ID;
-       task->tk_pid = rpc_task_id++;
-#endif
+       rpc_task_set_debuginfo(task);
        /* Add to global list of all tasks */
-       list_add_tail(&task->tk_task, &all_tasks);
-       spin_unlock(&rpc_sched_lock);
+       clnt = task->tk_client;
+       if (clnt != NULL) {
+               spin_lock(&clnt->cl_lock);
+               list_add_tail(&task->tk_task, &clnt->cl_tasks);
+               spin_unlock(&clnt->cl_lock);
+       }
 }
 
 /*
@@ -818,6 +821,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons
        if (tk_ops->rpc_call_prepare != NULL)
                task->tk_action = rpc_prepare_task;
        task->tk_calldata = calldata;
+       INIT_LIST_HEAD(&task->tk_task);
 
        /* Initialize retry counters */
        task->tk_garb_retry = 2;
@@ -830,7 +834,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons
        task->tk_workqueue = rpciod_workqueue;
 
        if (clnt) {
-               atomic_inc(&clnt->cl_users);
+               kref_get(&clnt->cl_kref);
                if (clnt->cl_softrtry)
                        task->tk_flags |= RPC_TASK_SOFT;
                if (!clnt->cl_intr)
@@ -860,9 +864,7 @@ static void rpc_free_task(struct rcu_head *rcu)
 }
 
 /*
- * Create a new task for the specified client.  We have to
- * clean up after an allocation failure, as the client may
- * have specified "oneshot".
+ * Create a new task for the specified client.
  */
 struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
 {
@@ -870,7 +872,7 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc
 
        task = rpc_alloc_task();
        if (!task)
-               goto cleanup;
+               goto out;
 
        rpc_init_task(task, clnt, flags, tk_ops, calldata);
 
@@ -878,16 +880,6 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc
        task->tk_flags |= RPC_TASK_DYNAMIC;
 out:
        return task;
-
-cleanup:
-       /* Check whether to release the client */
-       if (clnt) {
-               printk("rpc_new_task: failed, users=%d, oneshot=%d\n",
-                       atomic_read(&clnt->cl_users), clnt->cl_oneshot);
-               atomic_inc(&clnt->cl_users); /* pretend we were used ... */
-               rpc_release_client(clnt);
-       }
-       goto out;
 }
 
 
@@ -920,11 +912,13 @@ static void rpc_release_task(struct rpc_task *task)
 #endif
        dprintk("RPC: %5u release task\n", task->tk_pid);
 
-       /* Remove from global task list */
-       spin_lock(&rpc_sched_lock);
-       list_del(&task->tk_task);
-       spin_unlock(&rpc_sched_lock);
-
+       if (!list_empty(&task->tk_task)) {
+               struct rpc_clnt *clnt = task->tk_client;
+               /* Remove from client task list */
+               spin_lock(&clnt->cl_lock);
+               list_del(&task->tk_task);
+               spin_unlock(&clnt->cl_lock);
+       }
        BUG_ON (RPC_IS_QUEUED(task));
 
        /* Synchronously delete any running timer */
@@ -939,29 +933,6 @@ static void rpc_release_task(struct rpc_task *task)
        rpc_put_task(task);
 }
 
-/**
- * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
- * @clnt: pointer to RPC client
- * @flags: RPC flags
- * @ops: RPC call ops
- * @data: user call data
- */
-struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
-                                       const struct rpc_call_ops *ops,
-                                       void *data)
-{
-       struct rpc_task *task;
-       task = rpc_new_task(clnt, flags, ops, data);
-       if (task == NULL) {
-               rpc_release_calldata(ops, data);
-               return ERR_PTR(-ENOMEM);
-       }
-       atomic_inc(&task->tk_count);
-       rpc_execute(task);
-       return task;
-}
-EXPORT_SYMBOL(rpc_run_task);
-
 /*
  * Kill all tasks for the given client.
  * XXX: kill their descendants as well?
@@ -969,44 +940,25 @@ EXPORT_SYMBOL(rpc_run_task);
 void rpc_killall_tasks(struct rpc_clnt *clnt)
 {
        struct rpc_task *rovr;
-       struct list_head *le;
 
-       dprintk("RPC:       killing all tasks for client %p\n", clnt);
 
+       if (list_empty(&clnt->cl_tasks))
+               return;
+       dprintk("RPC:       killing all tasks for client %p\n", clnt);
        /*
         * Spin lock all_tasks to prevent changes...
         */
-       spin_lock(&rpc_sched_lock);
-       alltask_for_each(rovr, le, &all_tasks) {
+       spin_lock(&clnt->cl_lock);
+       list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) {
                if (! RPC_IS_ACTIVATED(rovr))
                        continue;
-               if (!clnt || rovr->tk_client == clnt) {
+               if (!(rovr->tk_flags & RPC_TASK_KILLED)) {
                        rovr->tk_flags |= RPC_TASK_KILLED;
                        rpc_exit(rovr, -EIO);
                        rpc_wake_up_task(rovr);
                }
        }
-       spin_unlock(&rpc_sched_lock);
-}
-
-static void rpciod_killall(void)
-{
-       unsigned long flags;
-
-       while (!list_empty(&all_tasks)) {
-               clear_thread_flag(TIF_SIGPENDING);
-               rpc_killall_tasks(NULL);
-               flush_workqueue(rpciod_workqueue);
-               if (!list_empty(&all_tasks)) {
-                       dprintk("RPC:       rpciod_killall: waiting for tasks "
-                                       "to exit\n");
-                       yield();
-               }
-       }
-
-       spin_lock_irqsave(&current->sighand->siglock, flags);
-       recalc_sigpending();
-       spin_unlock_irqrestore(&current->sighand->siglock, flags);
+       spin_unlock(&clnt->cl_lock);
 }
 
 /*
@@ -1018,28 +970,27 @@ rpciod_up(void)
        struct workqueue_struct *wq;
        int error = 0;
 
+       if (atomic_inc_not_zero(&rpciod_users))
+               return 0;
+
        mutex_lock(&rpciod_mutex);
-       dprintk("RPC:       rpciod_up: users %u\n", rpciod_users);
-       rpciod_users++;
-       if (rpciod_workqueue)
-               goto out;
-       /*
-        * If there's no pid, we should be the first user.
-        */
-       if (rpciod_users > 1)
-               printk(KERN_WARNING "rpciod_up: no workqueue, %u users??\n", rpciod_users);
+
+       /* Guard against races with rpciod_down() */
+       if (rpciod_workqueue != NULL)
+               goto out_ok;
        /*
         * Create the rpciod thread and wait for it to start.
         */
+       dprintk("RPC:       creating workqueue rpciod\n");
        error = -ENOMEM;
        wq = create_workqueue("rpciod");
-       if (wq == NULL) {
-               printk(KERN_WARNING "rpciod_up: create workqueue failed, error=%d\n", error);
-               rpciod_users--;
+       if (wq == NULL)
                goto out;
-       }
+
        rpciod_workqueue = wq;
        error = 0;
+out_ok:
+       atomic_inc(&rpciod_users);
 out:
        mutex_unlock(&rpciod_mutex);
        return error;
@@ -1048,59 +999,19 @@ out:
 void
 rpciod_down(void)
 {
+       if (!atomic_dec_and_test(&rpciod_users))
+               return;
+
        mutex_lock(&rpciod_mutex);
-       dprintk("RPC:       rpciod_down sema %u\n", rpciod_users);
-       if (rpciod_users) {
-               if (--rpciod_users)
-                       goto out;
-       } else
-               printk(KERN_WARNING "rpciod_down: no users??\n");
+       dprintk("RPC:       destroying workqueue rpciod\n");
 
-       if (!rpciod_workqueue) {
-               dprintk("RPC:       rpciod_down: Nothing to do!\n");
-               goto out;
+       if (atomic_read(&rpciod_users) == 0 && rpciod_workqueue != NULL) {
+               destroy_workqueue(rpciod_workqueue);
+               rpciod_workqueue = NULL;
        }
-       rpciod_killall();
-
-       destroy_workqueue(rpciod_workqueue);
-       rpciod_workqueue = NULL;
- out:
        mutex_unlock(&rpciod_mutex);
 }
 
-#ifdef RPC_DEBUG
-void rpc_show_tasks(void)
-{
-       struct list_head *le;
-       struct rpc_task *t;
-
-       spin_lock(&rpc_sched_lock);
-       if (list_empty(&all_tasks)) {
-               spin_unlock(&rpc_sched_lock);
-               return;
-       }
-       printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
-               "-rpcwait -action- ---ops--\n");
-       alltask_for_each(t, le, &all_tasks) {
-               const char *rpc_waitq = "none";
-
-               if (RPC_IS_QUEUED(t))
-                       rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
-
-               printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
-                       t->tk_pid,
-                       (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
-                       t->tk_flags, t->tk_status,
-                       t->tk_client,
-                       (t->tk_client ? t->tk_client->cl_prog : 0),
-                       t->tk_rqstp, t->tk_timeout,
-                       rpc_waitq,
-                       t->tk_action, t->tk_ops);
-       }
-       spin_unlock(&rpc_sched_lock);
-}
-#endif
-
 void
 rpc_destroy_mempool(void)
 {
index 73075dec83c07e4d73503156ca22668519cdfcf5..384c4ad5ab86db1b2e657d46efdd46a609b808a0 100644 (file)
@@ -28,15 +28,11 @@ EXPORT_SYMBOL(rpc_init_task);
 EXPORT_SYMBOL(rpc_sleep_on);
 EXPORT_SYMBOL(rpc_wake_up_next);
 EXPORT_SYMBOL(rpc_wake_up_task);
-EXPORT_SYMBOL(rpciod_down);
-EXPORT_SYMBOL(rpciod_up);
-EXPORT_SYMBOL(rpc_new_task);
 EXPORT_SYMBOL(rpc_wake_up_status);
 
 /* RPC client functions */
 EXPORT_SYMBOL(rpc_clone_client);
 EXPORT_SYMBOL(rpc_bind_new_program);
-EXPORT_SYMBOL(rpc_destroy_client);
 EXPORT_SYMBOL(rpc_shutdown_client);
 EXPORT_SYMBOL(rpc_killall_tasks);
 EXPORT_SYMBOL(rpc_call_sync);
@@ -61,7 +57,7 @@ EXPORT_SYMBOL(rpcauth_unregister);
 EXPORT_SYMBOL(rpcauth_create);
 EXPORT_SYMBOL(rpcauth_lookupcred);
 EXPORT_SYMBOL(rpcauth_lookup_credcache);
-EXPORT_SYMBOL(rpcauth_free_credcache);
+EXPORT_SYMBOL(rpcauth_destroy_credcache);
 EXPORT_SYMBOL(rpcauth_init_credcache);
 EXPORT_SYMBOL(put_rpccred);
 
@@ -156,6 +152,7 @@ init_sunrpc(void)
        cache_register(&ip_map_cache);
        cache_register(&unix_gid_cache);
        init_socket_xprt();
+       rpcauth_init_module();
 out:
        return err;
 }
@@ -163,6 +160,7 @@ out:
 static void __exit
 cleanup_sunrpc(void)
 {
+       rpcauth_remove_module();
        cleanup_socket_xprt();
        unregister_rpc_pipefs();
        rpc_destroy_mempool();
index 5baf48de25588f9e6610e1e1fdadeac4400636bd..64b9b8c743c49b67eedc041ba7a90bcf06abb85b 100644 (file)
@@ -644,6 +644,7 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
        struct msghdr msg = {
                .msg_flags      = MSG_DONTWAIT,
        };
+       struct sockaddr *sin;
        int len;
 
        len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
@@ -654,6 +655,19 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
        memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen);
        rqstp->rq_addrlen = svsk->sk_remotelen;
 
+       /* Destination address in request is needed for binding the
+        * source address in RPC callbacks later.
+        */
+       sin = (struct sockaddr *)&svsk->sk_local;
+       switch (sin->sa_family) {
+       case AF_INET:
+               rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr;
+               break;
+       case AF_INET6:
+               rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr;
+               break;
+       }
+
        dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
                svsk, iov[0].iov_base, iov[0].iov_len, len);
 
@@ -1064,6 +1078,12 @@ svc_tcp_accept(struct svc_sock *svsk)
                goto failed;
        memcpy(&newsvsk->sk_remote, sin, slen);
        newsvsk->sk_remotelen = slen;
+       err = kernel_getsockname(newsock, sin, &slen);
+       if (unlikely(err < 0)) {
+               dprintk("svc_tcp_accept: kernel_getsockname error %d\n", -err);
+               slen = offsetof(struct sockaddr, sa_data);
+       }
+       memcpy(&newsvsk->sk_local, sin, slen);
 
        svc_sock_received(newsvsk);
 
index 5b05b73e4c1d3f7a52c189e05b1ba55461c3270f..c8c2edccad7e0dc2db35c754c9b56890a7c73965 100644 (file)
@@ -127,7 +127,7 @@ static void xprt_clear_locked(struct rpc_xprt *xprt)
                clear_bit(XPRT_LOCKED, &xprt->state);
                smp_mb__after_clear_bit();
        } else
-               schedule_work(&xprt->task_cleanup);
+               queue_work(rpciod_workqueue, &xprt->task_cleanup);
 }
 
 /*
@@ -515,7 +515,7 @@ xprt_init_autodisconnect(unsigned long data)
        if (xprt_connecting(xprt))
                xprt_release_write(xprt, NULL);
        else
-               schedule_work(&xprt->task_cleanup);
+               queue_work(rpciod_workqueue, &xprt->task_cleanup);
        return;
 out_abort:
        spin_unlock(&xprt->transport_lock);
@@ -886,27 +886,24 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i
 
 /**
  * xprt_create_transport - create an RPC transport
- * @proto: requested transport protocol
- * @ap: remote peer address
- * @size: length of address
- * @to: timeout parameters
+ * @args: rpc transport creation arguments
  *
  */
-struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t size, struct rpc_timeout *to)
+struct rpc_xprt *xprt_create_transport(struct rpc_xprtsock_create *args)
 {
        struct rpc_xprt *xprt;
        struct rpc_rqst *req;
 
-       switch (proto) {
+       switch (args->proto) {
        case IPPROTO_UDP:
-               xprt = xs_setup_udp(ap, size, to);
+               xprt = xs_setup_udp(args);
                break;
        case IPPROTO_TCP:
-               xprt = xs_setup_tcp(ap, size, to);
+               xprt = xs_setup_tcp(args);
                break;
        default:
                printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
-                               proto);
+                               args->proto);
                return ERR_PTR(-EIO);
        }
        if (IS_ERR(xprt)) {
index cc33c5880abb477eb3cdb7d415e2f7df91f303b1..4ae7eed7f6170b665845344ab95663975c09a38a 100644 (file)
@@ -235,6 +235,7 @@ struct sock_xprt {
         * Connection of transports
         */
        struct delayed_work     connect_worker;
+       struct sockaddr_storage addr;
        unsigned short          port;
 
        /*
@@ -653,8 +654,7 @@ static void xs_destroy(struct rpc_xprt *xprt)
 
        dprintk("RPC:       xs_destroy xprt %p\n", xprt);
 
-       cancel_delayed_work(&transport->connect_worker);
-       flush_scheduled_work();
+       cancel_rearming_delayed_work(&transport->connect_worker);
 
        xprt_disconnect(xprt);
        xs_close(xprt);
@@ -1001,7 +1001,7 @@ static void xs_tcp_state_change(struct sock *sk)
                /* Try to schedule an autoclose RPC calls */
                set_bit(XPRT_CLOSE_WAIT, &xprt->state);
                if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
-                       schedule_work(&xprt->task_cleanup);
+                       queue_work(rpciod_workqueue, &xprt->task_cleanup);
        default:
                xprt_disconnect(xprt);
        }
@@ -1146,31 +1146,36 @@ static void xs_set_port(struct rpc_xprt *xprt, unsigned short port)
        sap->sin_port = htons(port);
 }
 
-static int xs_bindresvport(struct sock_xprt *transport, struct socket *sock)
+static int xs_bind(struct sock_xprt *transport, struct socket *sock)
 {
        struct sockaddr_in myaddr = {
                .sin_family = AF_INET,
        };
+       struct sockaddr_in *sa;
        int err;
        unsigned short port = transport->port;
 
+       if (!transport->xprt.resvport)
+               port = 0;
+       sa = (struct sockaddr_in *)&transport->addr;
+       myaddr.sin_addr = sa->sin_addr;
        do {
                myaddr.sin_port = htons(port);
                err = kernel_bind(sock, (struct sockaddr *) &myaddr,
                                                sizeof(myaddr));
+               if (!transport->xprt.resvport)
+                       break;
                if (err == 0) {
                        transport->port = port;
-                       dprintk("RPC:       xs_bindresvport bound to port %u\n",
-                                       port);
-                       return 0;
+                       break;
                }
                if (port <= xprt_min_resvport)
                        port = xprt_max_resvport;
                else
                        port--;
        } while (err == -EADDRINUSE && port != transport->port);
-
-       dprintk("RPC:       can't bind to reserved port (%d).\n", -err);
+       dprintk("RPC:       xs_bind "NIPQUAD_FMT":%u: %s (%d)\n",
+               NIPQUAD(myaddr.sin_addr), port, err ? "failed" : "ok", err);
        return err;
 }
 
@@ -1229,7 +1234,7 @@ static void xs_udp_connect_worker(struct work_struct *work)
        }
        xs_reclassify_socket(sock);
 
-       if (xprt->resvport && xs_bindresvport(transport, sock) < 0) {
+       if (xs_bind(transport, sock)) {
                sock_release(sock);
                goto out;
        }
@@ -1316,7 +1321,7 @@ static void xs_tcp_connect_worker(struct work_struct *work)
                }
                xs_reclassify_socket(sock);
 
-               if (xprt->resvport && xs_bindresvport(transport, sock) < 0) {
+               if (xs_bind(transport, sock)) {
                        sock_release(sock);
                        goto out;
                }
@@ -1410,18 +1415,16 @@ static void xs_connect(struct rpc_task *task)
                dprintk("RPC:       xs_connect delayed xprt %p for %lu "
                                "seconds\n",
                                xprt, xprt->reestablish_timeout / HZ);
-               schedule_delayed_work(&transport->connect_worker,
-                                       xprt->reestablish_timeout);
+               queue_delayed_work(rpciod_workqueue,
+                                  &transport->connect_worker,
+                                  xprt->reestablish_timeout);
                xprt->reestablish_timeout <<= 1;
                if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
                        xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
        } else {
                dprintk("RPC:       xs_connect scheduled xprt %p\n", xprt);
-               schedule_delayed_work(&transport->connect_worker, 0);
-
-               /* flush_scheduled_work can sleep... */
-               if (!RPC_IS_ASYNC(task))
-                       flush_scheduled_work();
+               queue_delayed_work(rpciod_workqueue,
+                                  &transport->connect_worker, 0);
        }
 }
 
@@ -1476,7 +1479,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
        .set_buffer_size        = xs_udp_set_buffer_size,
        .reserve_xprt           = xprt_reserve_xprt_cong,
        .release_xprt           = xprt_release_xprt_cong,
-       .rpcbind                = rpcb_getport,
+       .rpcbind                = rpcb_getport_async,
        .set_port               = xs_set_port,
        .connect                = xs_connect,
        .buf_alloc              = rpc_malloc,
@@ -1493,7 +1496,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
 static struct rpc_xprt_ops xs_tcp_ops = {
        .reserve_xprt           = xprt_reserve_xprt,
        .release_xprt           = xs_tcp_release_xprt,
-       .rpcbind                = rpcb_getport,
+       .rpcbind                = rpcb_getport_async,
        .set_port               = xs_set_port,
        .connect                = xs_connect,
        .buf_alloc              = rpc_malloc,
@@ -1505,12 +1508,12 @@ static struct rpc_xprt_ops xs_tcp_ops = {
        .print_stats            = xs_tcp_print_stats,
 };
 
-static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, unsigned int slot_table_size)
+static struct rpc_xprt *xs_setup_xprt(struct rpc_xprtsock_create *args, unsigned int slot_table_size)
 {
        struct rpc_xprt *xprt;
        struct sock_xprt *new;
 
-       if (addrlen > sizeof(xprt->addr)) {
+       if (args->addrlen > sizeof(xprt->addr)) {
                dprintk("RPC:       xs_setup_xprt: address too large\n");
                return ERR_PTR(-EBADF);
        }
@@ -1532,8 +1535,10 @@ static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, uns
                return ERR_PTR(-ENOMEM);
        }
 
-       memcpy(&xprt->addr, addr, addrlen);
-       xprt->addrlen = addrlen;
+       memcpy(&xprt->addr, args->dstaddr, args->addrlen);
+       xprt->addrlen = args->addrlen;
+       if (args->srcaddr)
+               memcpy(&new->addr, args->srcaddr, args->addrlen);
        new->port = xs_get_random_port();
 
        return xprt;
@@ -1541,22 +1546,20 @@ static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, uns
 
 /**
  * xs_setup_udp - Set up transport to use a UDP socket
- * @addr: address of remote server
- * @addrlen: length of address in bytes
- * @to:   timeout parameters
+ * @args: rpc transport creation arguments
  *
  */
-struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
+struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args)
 {
        struct rpc_xprt *xprt;
        struct sock_xprt *transport;
 
-       xprt = xs_setup_xprt(addr, addrlen, xprt_udp_slot_table_entries);
+       xprt = xs_setup_xprt(args, xprt_udp_slot_table_entries);
        if (IS_ERR(xprt))
                return xprt;
        transport = container_of(xprt, struct sock_xprt, xprt);
 
-       if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
+       if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0)
                xprt_set_bound(xprt);
 
        xprt->prot = IPPROTO_UDP;
@@ -1572,8 +1575,8 @@ struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_
 
        xprt->ops = &xs_udp_ops;
 
-       if (to)
-               xprt->timeout = *to;
+       if (args->timeout)
+               xprt->timeout = *args->timeout;
        else
                xprt_set_timeout(&xprt->timeout, 5, 5 * HZ);
 
@@ -1586,22 +1589,20 @@ struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_
 
 /**
  * xs_setup_tcp - Set up transport to use a TCP socket
- * @addr: address of remote server
- * @addrlen: length of address in bytes
- * @to: timeout parameters
+ * @args: rpc transport creation arguments
  *
  */
-struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
+struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args)
 {
        struct rpc_xprt *xprt;
        struct sock_xprt *transport;
 
-       xprt = xs_setup_xprt(addr, addrlen, xprt_tcp_slot_table_entries);
+       xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
        if (IS_ERR(xprt))
                return xprt;
        transport = container_of(xprt, struct sock_xprt, xprt);
 
-       if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
+       if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0)
                xprt_set_bound(xprt);
 
        xprt->prot = IPPROTO_TCP;
@@ -1616,8 +1617,8 @@ struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_
 
        xprt->ops = &xs_tcp_ops;
 
-       if (to)
-               xprt->timeout = *to;
+       if (args->timeout)
+               xprt->timeout = *args->timeout;
        else
                xprt_set_timeout(&xprt->timeout, 2, 60 * HZ);
 
index 8ffd76405b5b69f0b61057be0ffc3fb2af6adb6a..d6a112ce2975c847390fed605ade3d532f4fe03a 100644 (file)
@@ -420,8 +420,12 @@ static int dummy_file_ioctl (struct file *file, unsigned int command,
 
 static int dummy_file_mmap (struct file *file, unsigned long reqprot,
                            unsigned long prot,
-                           unsigned long flags)
+                           unsigned long flags,
+                           unsigned long addr,
+                           unsigned long addr_only)
 {
+       if (addr < mmap_min_addr)
+               return -EACCES;
        return 0;
 }
 
index fc8601b2b7acabde473cc86a0fdc4b342a00e97a..27e5863d30f1f916393e855a6bfa496475a8fa71 100644 (file)
@@ -24,6 +24,7 @@ extern struct security_operations dummy_security_ops;
 extern void security_fixup_ops(struct security_operations *ops);
 
 struct security_operations *security_ops;      /* Initialized to NULL */
+unsigned long mmap_min_addr;           /* 0 means no protection */
 
 static inline int verify(struct security_operations *ops)
 {
index e4396a89edc620dfd8e52aafebe7273c30869c0a..78c408fd2b02cdf66e2e9331304da6b1bf352116 100644 (file)
@@ -586,7 +586,7 @@ void avc_audit(u32 ssid, u32 tsid,
                                }
                        }
                        if (inode)
-                               audit_log_format(ab, " dev=%s ino=%ld",
+                               audit_log_format(ab, " dev=%s ino=%lu",
                                                 inode->i_sb->s_id,
                                                 inode->i_ino);
                        break;
@@ -832,6 +832,7 @@ int avc_ss_reset(u32 seqno)
  * @tsid: target security identifier
  * @tclass: target security class
  * @requested: requested permissions, interpreted based on @tclass
+ * @flags:  AVC_STRICT or 0
  * @avd: access vector decisions
  *
  * Check the AVC to determine whether the @requested permissions are granted
@@ -846,8 +847,9 @@ int avc_ss_reset(u32 seqno)
  * should be released for the auditing.
  */
 int avc_has_perm_noaudit(u32 ssid, u32 tsid,
-                         u16 tclass, u32 requested,
-                         struct av_decision *avd)
+                        u16 tclass, u32 requested,
+                        unsigned flags,
+                        struct av_decision *avd)
 {
        struct avc_node *node;
        struct avc_entry entry, *p_ae;
@@ -874,7 +876,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
        denied = requested & ~(p_ae->avd.allowed);
 
        if (!requested || denied) {
-               if (selinux_enforcing)
+               if (selinux_enforcing || (flags & AVC_STRICT))
                        rc = -EACCES;
                else
                        if (node)
@@ -909,7 +911,7 @@ int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
        struct av_decision avd;
        int rc;
 
-       rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd);
+       rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
        avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
        return rc;
 }
index ad8dd4e8657e5487bd7668328238c166248176da..78c3f98fcdcfa94b2bf72a2bbcc7158b11756eba 100644 (file)
@@ -1592,9 +1592,10 @@ static int selinux_vm_enough_memory(long pages)
        rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
        if (rc == 0)
                rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
-                                       SECCLASS_CAPABILITY,
-                                       CAP_TO_MASK(CAP_SYS_ADMIN),
-                                       NULL);
+                                         SECCLASS_CAPABILITY,
+                                         CAP_TO_MASK(CAP_SYS_ADMIN),
+                                         0,
+                                         NULL);
 
        if (rc == 0)
                cap_sys_admin = 1;
@@ -2568,12 +2569,16 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
 }
 
 static int selinux_file_mmap(struct file *file, unsigned long reqprot,
-                            unsigned long prot, unsigned long flags)
+                            unsigned long prot, unsigned long flags,
+                            unsigned long addr, unsigned long addr_only)
 {
-       int rc;
+       int rc = 0;
+       u32 sid = ((struct task_security_struct*)(current->security))->sid;
 
-       rc = secondary_ops->file_mmap(file, reqprot, prot, flags);
-       if (rc)
+       if (addr < mmap_min_addr)
+               rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
+                                 MEMPROTECT__MMAP_ZERO, NULL);
+       if (rc || addr_only)
                return rc;
 
        if (selinux_checkreqprot)
@@ -4626,7 +4631,7 @@ static int selinux_setprocattr(struct task_struct *p,
                if (p->ptrace & PT_PTRACED) {
                        error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
                                                     SECCLASS_PROCESS,
-                                                    PROCESS__PTRACE, &avd);
+                                                    PROCESS__PTRACE, 0, &avd);
                        if (!error)
                                tsec->sid = sid;
                        task_unlock(p);
index b83e74012a979ee8bc935921fa686496fd82f681..049bf69429b66d2566abc5bb063c19fc41647095 100644 (file)
    S_(SECCLASS_KEY, KEY__CREATE, "create")
    S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
    S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
+   S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero")
index 5fee1735bffe423d78cb559e1cb3ee529b6ced5f..eda89a2ec635db3ec67e546af97cd5d76dedc565 100644 (file)
 #define DCCP_SOCKET__NAME_BIND                    0x00200000UL
 #define DCCP_SOCKET__NODE_BIND                    0x00400000UL
 #define DCCP_SOCKET__NAME_CONNECT                 0x00800000UL
+#define MEMPROTECT__MMAP_ZERO                     0x00000001UL
index 6ed10c3d3339baf03cb8e79d0357b078a14427bf..e145f6e13b0b6b711c632b849bf1f83d9d125e65 100644 (file)
@@ -102,9 +102,11 @@ void avc_audit(u32 ssid, u32 tsid,
                u16 tclass, u32 requested,
                struct av_decision *avd, int result, struct avc_audit_data *auditdata);
 
+#define AVC_STRICT 1 /* Ignore permissive mode. */
 int avc_has_perm_noaudit(u32 ssid, u32 tsid,
-                         u16 tclass, u32 requested,
-                         struct av_decision *avd);
+                        u16 tclass, u32 requested,
+                        unsigned flags,
+                        struct av_decision *avd);
 
 int avc_has_perm(u32 ssid, u32 tsid,
                  u16 tclass, u32 requested,
index 3787990684418f540974541d3c6b68078b4c72c4..e77de0e62ea0e00deae7c92822d61b5ba9e82ce0 100644 (file)
@@ -63,3 +63,4 @@
     S_("key")
     S_(NULL)
     S_("dccp_socket")
+    S_("memprotect")
index 35f309f478731aa0ea116c81055cdfd72a77460f..a9c2b20f14b5c0584085180c272875453b9796c9 100644 (file)
@@ -49,6 +49,7 @@
 #define SECCLASS_PACKET                                  57
 #define SECCLASS_KEY                                     58
 #define SECCLASS_DCCP_SOCKET                             60
+#define SECCLASS_MEMPROTECT                              61
 
 /*
  * Security identifier indices for initial entities
index b94378afea251d124a7308d5bca790a72a72f3f0..83bdd4d2a29e1ad4713367e2b506a3e756c1079f 100644 (file)
@@ -41,6 +41,7 @@ extern int selinux_mls_enabled;
 
 int security_load_policy(void * data, size_t len);
 
+#define SEL_VEC_MAX 32
 struct av_decision {
        u32 allowed;
        u32 decided;
@@ -87,6 +88,9 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
 
 int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
 
+int security_get_classes(char ***classes, int *nclasses);
+int security_get_permissions(char *class, char ***perms, int *nperms);
+
 #define SECURITY_FS_USE_XATTR          1 /* use xattr */
 #define SECURITY_FS_USE_TRANS          2 /* use transition SIDs, e.g. devpts/tmpfs */
 #define SECURITY_FS_USE_TASK           3 /* use task SIDs, e.g. pipefs/sockfs */
index aca099aa2ed3d743e65d38a4c77da690e4609e2f..c9e92daedee2c72c0860d8c0ff2cfcfc7b16a38d 100644 (file)
@@ -67,6 +67,10 @@ static struct dentry *bool_dir = NULL;
 static int bool_num = 0;
 static int *bool_pending_values = NULL;
 
+/* global data for classes */
+static struct dentry *class_dir = NULL;
+static unsigned long last_class_ino;
+
 extern void selnl_notify_setenforce(int val);
 
 /* Check whether a task is allowed to use a security operation. */
@@ -106,6 +110,7 @@ static unsigned long sel_last_ino = SEL_INO_NEXT - 1;
 
 #define SEL_INITCON_INO_OFFSET         0x01000000
 #define SEL_BOOL_INO_OFFSET    0x02000000
+#define SEL_CLASS_INO_OFFSET   0x04000000
 #define SEL_INO_MASK           0x00ffffff
 
 #define TMPBUFLEN      12
@@ -237,6 +242,11 @@ static const struct file_operations sel_policyvers_ops = {
 
 /* declaration for sel_write_load */
 static int sel_make_bools(void);
+static int sel_make_classes(void);
+
+/* declaration for sel_make_class_dirs */
+static int sel_make_dir(struct inode *dir, struct dentry *dentry,
+                       unsigned long *ino);
 
 static ssize_t sel_read_mls(struct file *filp, char __user *buf,
                                size_t count, loff_t *ppos)
@@ -287,10 +297,18 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
                goto out;
 
        ret = sel_make_bools();
+       if (ret) {
+               length = ret;
+               goto out1;
+       }
+
+       ret = sel_make_classes();
        if (ret)
                length = ret;
        else
                length = count;
+
+out1:
        audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
                "policy loaded auid=%u",
                audit_get_loginuid(current->audit_context));
@@ -940,9 +958,8 @@ static const struct file_operations sel_commit_bools_ops = {
        .write          = sel_commit_bools_write,
 };
 
-/* delete booleans - partial revoke() from
- * fs/proc/generic.c proc_kill_inodes */
-static void sel_remove_bools(struct dentry *de)
+/* partial revoke() from fs/proc/generic.c proc_kill_inodes */
+static void sel_remove_entries(struct dentry *de)
 {
        struct list_head *p, *node;
        struct super_block *sb = de->d_sb;
@@ -998,7 +1015,7 @@ static int sel_make_bools(void)
        kfree(bool_pending_values);
        bool_pending_values = NULL;
 
-       sel_remove_bools(dir);
+       sel_remove_entries(dir);
 
        if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
                return -ENOMEM;
@@ -1048,7 +1065,7 @@ out:
        return ret;
 err:
        kfree(values);
-       sel_remove_bools(dir);
+       sel_remove_entries(dir);
        ret = -ENOMEM;
        goto out;
 }
@@ -1294,7 +1311,227 @@ out:
        return ret;
 }
 
-static int sel_make_dir(struct inode *dir, struct dentry *dentry)
+static inline unsigned int sel_div(unsigned long a, unsigned long b)
+{
+       return a / b - (a % b < 0);
+}
+
+static inline unsigned long sel_class_to_ino(u16 class)
+{
+       return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET;
+}
+
+static inline u16 sel_ino_to_class(unsigned long ino)
+{
+       return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1);
+}
+
+static inline unsigned long sel_perm_to_ino(u16 class, u32 perm)
+{
+       return (class * (SEL_VEC_MAX + 1) + perm) | SEL_CLASS_INO_OFFSET;
+}
+
+static inline u32 sel_ino_to_perm(unsigned long ino)
+{
+       return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1);
+}
+
+static ssize_t sel_read_class(struct file * file, char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       ssize_t rc, len;
+       char *page;
+       unsigned long ino = file->f_path.dentry->d_inode->i_ino;
+
+       page = (char *)__get_free_page(GFP_KERNEL);
+       if (!page) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino));
+       rc = simple_read_from_buffer(buf, count, ppos, page, len);
+       free_page((unsigned long)page);
+out:
+       return rc;
+}
+
+static const struct file_operations sel_class_ops = {
+       .read           = sel_read_class,
+};
+
+static ssize_t sel_read_perm(struct file * file, char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       ssize_t rc, len;
+       char *page;
+       unsigned long ino = file->f_path.dentry->d_inode->i_ino;
+
+       page = (char *)__get_free_page(GFP_KERNEL);
+       if (!page) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       len = snprintf(page, PAGE_SIZE,"%d", sel_ino_to_perm(ino));
+       rc = simple_read_from_buffer(buf, count, ppos, page, len);
+       free_page((unsigned long)page);
+out:
+       return rc;
+}
+
+static const struct file_operations sel_perm_ops = {
+       .read           = sel_read_perm,
+};
+
+static int sel_make_perm_files(char *objclass, int classvalue,
+                               struct dentry *dir)
+{
+       int i, rc = 0, nperms;
+       char **perms;
+
+       rc = security_get_permissions(objclass, &perms, &nperms);
+       if (rc)
+               goto out;
+
+       for (i = 0; i < nperms; i++) {
+               struct inode *inode;
+               struct dentry *dentry;
+
+               dentry = d_alloc_name(dir, perms[i]);
+               if (!dentry) {
+                       rc = -ENOMEM;
+                       goto out1;
+               }
+
+               inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
+               if (!inode) {
+                       rc = -ENOMEM;
+                       goto out1;
+               }
+               inode->i_fop = &sel_perm_ops;
+               /* i+1 since perm values are 1-indexed */
+               inode->i_ino = sel_perm_to_ino(classvalue, i+1);
+               d_add(dentry, inode);
+       }
+
+out1:
+       for (i = 0; i < nperms; i++)
+               kfree(perms[i]);
+       kfree(perms);
+out:
+       return rc;
+}
+
+static int sel_make_class_dir_entries(char *classname, int index,
+                                       struct dentry *dir)
+{
+       struct dentry *dentry = NULL;
+       struct inode *inode = NULL;
+       int rc;
+
+       dentry = d_alloc_name(dir, "index");
+       if (!dentry) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
+       if (!inode) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       inode->i_fop = &sel_class_ops;
+       inode->i_ino = sel_class_to_ino(index);
+       d_add(dentry, inode);
+
+       dentry = d_alloc_name(dir, "perms");
+       if (!dentry) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino);
+       if (rc)
+               goto out;
+
+       rc = sel_make_perm_files(classname, index, dentry);
+
+out:
+       return rc;
+}
+
+static void sel_remove_classes(void)
+{
+       struct list_head *class_node;
+
+       list_for_each(class_node, &class_dir->d_subdirs) {
+               struct dentry *class_subdir = list_entry(class_node,
+                                       struct dentry, d_u.d_child);
+               struct list_head *class_subdir_node;
+
+               list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
+                       struct dentry *d = list_entry(class_subdir_node,
+                                               struct dentry, d_u.d_child);
+
+                       if (d->d_inode)
+                               if (d->d_inode->i_mode & S_IFDIR)
+                                       sel_remove_entries(d);
+               }
+
+               sel_remove_entries(class_subdir);
+       }
+
+       sel_remove_entries(class_dir);
+}
+
+static int sel_make_classes(void)
+{
+       int rc = 0, nclasses, i;
+       char **classes;
+
+       /* delete any existing entries */
+       sel_remove_classes();
+
+       rc = security_get_classes(&classes, &nclasses);
+       if (rc < 0)
+               goto out;
+
+       /* +2 since classes are 1-indexed */
+       last_class_ino = sel_class_to_ino(nclasses+2);
+
+       for (i = 0; i < nclasses; i++) {
+               struct dentry *class_name_dir;
+
+               class_name_dir = d_alloc_name(class_dir, classes[i]);
+               if (!class_name_dir) {
+                       rc = -ENOMEM;
+                       goto out1;
+               }
+
+               rc = sel_make_dir(class_dir->d_inode, class_name_dir,
+                               &last_class_ino);
+               if (rc)
+                       goto out1;
+
+               /* i+1 since class values are 1-indexed */
+               rc = sel_make_class_dir_entries(classes[i], i+1,
+                               class_name_dir);
+               if (rc)
+                       goto out1;
+       }
+
+out1:
+       for (i = 0; i < nclasses; i++)
+               kfree(classes[i]);
+       kfree(classes);
+out:
+       return rc;
+}
+
+static int sel_make_dir(struct inode *dir, struct dentry *dentry,
+                       unsigned long *ino)
 {
        int ret = 0;
        struct inode *inode;
@@ -1306,7 +1543,7 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry)
        }
        inode->i_op = &simple_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
-       inode->i_ino = ++sel_last_ino;
+       inode->i_ino = ++(*ino);
        /* directory inodes start off with i_nlink == 2 (for "." entry) */
        inc_nlink(inode);
        d_add(dentry, inode);
@@ -1352,7 +1589,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
                goto err;
        }
 
-       ret = sel_make_dir(root_inode, dentry);
+       ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
        if (ret)
                goto err;
 
@@ -1385,7 +1622,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
                goto err;
        }
 
-       ret = sel_make_dir(root_inode, dentry);
+       ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
        if (ret)
                goto err;
 
@@ -1399,7 +1636,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
                goto err;
        }
 
-       ret = sel_make_dir(root_inode, dentry);
+       ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
        if (ret)
                goto err;
 
@@ -1407,6 +1644,18 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
        if (ret)
                goto err;
 
+       dentry = d_alloc_name(sb->s_root, "class");
+       if (!dentry) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
+       if (ret)
+               goto err;
+
+       class_dir = dentry;
+
 out:
        return ret;
 err:
index 0ac1021734c01118a012b38ab7335b8eeeb2f4fa..f05f97a2bc3a1343e5960f1c409a8ae0e7e565f4 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -598,6 +599,7 @@ void policydb_destroy(struct policydb *p)
        struct range_trans *rt, *lrt = NULL;
 
        for (i = 0; i < SYM_NUM; i++) {
+               cond_resched();
                hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
                hashtab_destroy(p->symtab[i].table);
        }
@@ -612,6 +614,7 @@ void policydb_destroy(struct policydb *p)
        avtab_destroy(&p->te_avtab);
 
        for (i = 0; i < OCON_NUM; i++) {
+               cond_resched();
                c = p->ocontexts[i];
                while (c) {
                        ctmp = c;
@@ -623,6 +626,7 @@ void policydb_destroy(struct policydb *p)
 
        g = p->genfs;
        while (g) {
+               cond_resched();
                kfree(g->fstype);
                c = g->head;
                while (c) {
@@ -639,18 +643,21 @@ void policydb_destroy(struct policydb *p)
        cond_policydb_destroy(p);
 
        for (tr = p->role_tr; tr; tr = tr->next) {
+               cond_resched();
                kfree(ltr);
                ltr = tr;
        }
        kfree(ltr);
 
        for (ra = p->role_allow; ra; ra = ra -> next) {
+               cond_resched();
                kfree(lra);
                lra = ra;
        }
        kfree(lra);
 
        for (rt = p->range_tr; rt; rt = rt -> next) {
+               cond_resched();
                if (lrt) {
                        ebitmap_destroy(&lrt->target_range.level[0].cat);
                        ebitmap_destroy(&lrt->target_range.level[1].cat);
index 40660ffd49b64947c31ab32c617a316f407258d3..b5f017f07a75b6f614faf3cd9631fdc370936f0f 100644 (file)
@@ -1587,19 +1587,18 @@ int security_get_user_sids(u32 fromsid,
                           u32 *nel)
 {
        struct context *fromcon, usercon;
-       u32 *mysids, *mysids2, sid;
+       u32 *mysids = NULL, *mysids2, sid;
        u32 mynel = 0, maxnel = SIDS_NEL;
        struct user_datum *user;
        struct role_datum *role;
-       struct av_decision avd;
        struct ebitmap_node *rnode, *tnode;
        int rc = 0, i, j;
 
-       if (!ss_initialized) {
-               *sids = NULL;
-               *nel = 0;
+       *sids = NULL;
+       *nel = 0;
+
+       if (!ss_initialized)
                goto out;
-       }
 
        POLICY_RDLOCK;
 
@@ -1635,17 +1634,9 @@ int security_get_user_sids(u32 fromsid,
                        if (mls_setup_user_range(fromcon, user, &usercon))
                                continue;
 
-                       rc = context_struct_compute_av(fromcon, &usercon,
-                                                      SECCLASS_PROCESS,
-                                                      PROCESS__TRANSITION,
-                                                      &avd);
-                       if (rc ||  !(avd.allowed & PROCESS__TRANSITION))
-                               continue;
                        rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
-                       if (rc) {
-                               kfree(mysids);
+                       if (rc)
                                goto out_unlock;
-                       }
                        if (mynel < maxnel) {
                                mysids[mynel++] = sid;
                        } else {
@@ -1653,7 +1644,6 @@ int security_get_user_sids(u32 fromsid,
                                mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
                                if (!mysids2) {
                                        rc = -ENOMEM;
-                                       kfree(mysids);
                                        goto out_unlock;
                                }
                                memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
@@ -1664,11 +1654,32 @@ int security_get_user_sids(u32 fromsid,
                }
        }
 
-       *sids = mysids;
-       *nel = mynel;
-
 out_unlock:
        POLICY_RDUNLOCK;
+       if (rc || !mynel) {
+               kfree(mysids);
+               goto out;
+       }
+
+       mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
+       if (!mysids2) {
+               rc = -ENOMEM;
+               kfree(mysids);
+               goto out;
+       }
+       for (i = 0, j = 0; i < mynel; i++) {
+               rc = avc_has_perm_noaudit(fromsid, mysids[i],
+                                         SECCLASS_PROCESS,
+                                         PROCESS__TRANSITION, AVC_STRICT,
+                                         NULL);
+               if (!rc)
+                       mysids2[j++] = mysids[i];
+               cond_resched();
+       }
+       rc = 0;
+       kfree(mysids);
+       *sids = mysids2;
+       *nel = j;
 out:
        return rc;
 }
@@ -1996,6 +2007,101 @@ out:
        return rc;
 }
 
+static int get_classes_callback(void *k, void *d, void *args)
+{
+       struct class_datum *datum = d;
+       char *name = k, **classes = args;
+       int value = datum->value - 1;
+
+       classes[value] = kstrdup(name, GFP_ATOMIC);
+       if (!classes[value])
+               return -ENOMEM;
+
+       return 0;
+}
+
+int security_get_classes(char ***classes, int *nclasses)
+{
+       int rc = -ENOMEM;
+
+       POLICY_RDLOCK;
+
+       *nclasses = policydb.p_classes.nprim;
+       *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC);
+       if (!*classes)
+               goto out;
+
+       rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
+                       *classes);
+       if (rc < 0) {
+               int i;
+               for (i = 0; i < *nclasses; i++)
+                       kfree((*classes)[i]);
+               kfree(*classes);
+       }
+
+out:
+       POLICY_RDUNLOCK;
+       return rc;
+}
+
+static int get_permissions_callback(void *k, void *d, void *args)
+{
+       struct perm_datum *datum = d;
+       char *name = k, **perms = args;
+       int value = datum->value - 1;
+
+       perms[value] = kstrdup(name, GFP_ATOMIC);
+       if (!perms[value])
+               return -ENOMEM;
+
+       return 0;
+}
+
+int security_get_permissions(char *class, char ***perms, int *nperms)
+{
+       int rc = -ENOMEM, i;
+       struct class_datum *match;
+
+       POLICY_RDLOCK;
+
+       match = hashtab_search(policydb.p_classes.table, class);
+       if (!match) {
+               printk(KERN_ERR "%s:  unrecognized class %s\n",
+                       __FUNCTION__, class);
+               rc = -EINVAL;
+               goto out;
+       }
+
+       *nperms = match->permissions.nprim;
+       *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC);
+       if (!*perms)
+               goto out;
+
+       if (match->comdatum) {
+               rc = hashtab_map(match->comdatum->permissions.table,
+                               get_permissions_callback, *perms);
+               if (rc < 0)
+                       goto err;
+       }
+
+       rc = hashtab_map(match->permissions.table, get_permissions_callback,
+                       *perms);
+       if (rc < 0)
+               goto err;
+
+out:
+       POLICY_RDUNLOCK;
+       return rc;
+
+err:
+       POLICY_RDUNLOCK;
+       for (i = 0; i < *nperms; i++)
+               kfree((*perms)[i]);
+       kfree(*perms);
+       return rc;
+}
+
 struct selinux_audit_rule {
        u32 au_seqno;
        struct context au_ctxt;
index 16ac02540a3f77ac0ee591abe4e529abe8430e02..5058411b75243ef4da17a35883bd151fac1bca55 100644 (file)
@@ -1302,7 +1302,7 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
                goto err_irq;
        }
 
-       pci_read_config_byte(pci_dev, PCI_REVISION_ID, &card->chiprev);
+       card->chiprev = pci_dev->revision;
        pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &card->model);
 
        printk(KERN_INFO "emu10k1: %s rev %d model %#04x found, IO at %#04lx-%#04lx, IRQ %d\n",
index 593a3aac12ce50da78354877942c27b0c8053254..52648573f601f3c62b7db7fd3c54c1e5317db2fc 100644 (file)
@@ -2894,7 +2894,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
        s->irq = pcidev->irq;
        s->vendor = pcidev->vendor;
        s->device = pcidev->device;
-       pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
+       s->rev = pcidev->revision;
        s->codec->private_data = s;
        s->codec->id = 0;
        s->codec->codec_read = rdcodec;
index cb59f994c68f2a4bdfd2c9c1925d5b8cb2dd507d..41543a4933e7031c849892326df2ac3d43abb220 100644 (file)
@@ -2218,7 +2218,7 @@ static int __devinit snd_ali_create(struct snd_card *card,
        codec->card = card;
        codec->pci = pci;
        codec->irq = -1;
-       pci_read_config_byte(pci, PCI_REVISION_ID, &codec->revision);
+       codec->revision = pci->revision;
        codec->spdif_support = spdif_support;
 
        if (pcm_streams < 1)
index 7d8053b5e8d574fa23715d91de0b7fc580a48c7b..89184a424140232e91f0c832360593fbda21a5fe 100644 (file)
@@ -1639,15 +1639,12 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
 {
        struct snd_card *card;
        struct atiixp *chip;
-       unsigned char revision;
        int err;
 
        card = snd_card_new(index, id, THIS_MODULE, 0);
        if (card == NULL)
                return -ENOMEM;
 
-       pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
-
        strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA");
        strcpy(card->shortname, "ATI IXP");
        if ((err = snd_atiixp_create(card, pci, &chip)) < 0)
@@ -1670,7 +1667,8 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
        snd_atiixp_chip_start(chip);
 
        snprintf(card->longname, sizeof(card->longname),
-                "%s rev %x with %s at %#lx, irq %i", card->shortname, revision,
+                "%s rev %x with %s at %#lx, irq %i", card->shortname,
+                pci->revision,
                 chip->ac97[0] ? snd_ac97_get_short_name(chip->ac97[0]) : "?",
                 chip->addr, chip->irq);
 
index 904023fe4f26b902e49b11e347003e8e44741028..ce752f84457ad6ee9b6756a66c45557cfeb19e38 100644 (file)
@@ -1283,15 +1283,12 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
 {
        struct snd_card *card;
        struct atiixp_modem *chip;
-       unsigned char revision;
        int err;
 
        card = snd_card_new(index, id, THIS_MODULE, 0);
        if (card == NULL)
                return -ENOMEM;
 
-       pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
-
        strcpy(card->driver, "ATIIXP-MODEM");
        strcpy(card->shortname, "ATI IXP Modem");
        if ((err = snd_atiixp_create(card, pci, &chip)) < 0)
@@ -1312,7 +1309,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
        snd_atiixp_chip_start(chip);
 
        sprintf(card->longname, "%s rev %x at 0x%lx, irq %i",
-               card->shortname, revision, chip->addr, chip->irq);
+               card->shortname, pci->revision, chip->addr, chip->irq);
 
        if ((err = snd_card_register(card)) < 0)
                goto __error;
index 238154bb7a254695894e5bd1bea6e38cdba5d92c..5ec1b6fcd548e2623fd1b023dfe570cfbacd94e0 100644 (file)
@@ -341,11 +341,7 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                snd_card_free(card);
                return err;
        }
-       if ((err = pci_read_config_byte(pci, PCI_REVISION_ID,
-                                 &(chip->rev))) < 0) {
-               snd_card_free(card);
-               return err;
-       }
+       chip->rev = pci->revision;
 #ifdef CHIP_AU8830
        if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) {
                printk(KERN_ALERT
index aaac6e5b47676c07f1966a6ce0c709ace94d738f..a0420bc63f0bdbf1cd28fa9dfb20f94be6ffd7dd 100644 (file)
@@ -590,7 +590,6 @@ struct snd_ca0106 {
        struct resource *res_port;
        int irq;
 
-       unsigned char revision;         /* chip revision */
        unsigned int serial;            /* serial number */
        unsigned short model;           /* subsystem id */
 
index 48f3f17c5170283a4e18b7df9ec44f3570a58520..9fd7b8a5b75ec00ae24675789805debdc92849bc 100644 (file)
@@ -1293,13 +1293,12 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
        }
 
        pci_set_master(pci);
-       /* read revision & serial */
-       pci_read_config_byte(pci, PCI_REVISION_ID, &chip->revision);
+       /* read serial */
        pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
        pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
 #if 1
        printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
-              chip->revision, chip->serial);
+              pci->revision, chip->serial);
 #endif
        strcpy(card->driver, "CA0106");
        strcpy(card->shortname, "CA0106");
index dbc805c33fc440795a82b7c339b0750b1c64f21e..4a9b59ad8ab12592a34420b961d1f118d4dbb346 100644 (file)
@@ -1511,7 +1511,6 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
        struct snd_emu10k1 *emu;
        int idx, err;
        int is_audigy;
-       unsigned char revision;
        unsigned int silent_page;
        const struct snd_emu_chip_details *c;
        static struct snd_device_ops ops = {
@@ -1543,8 +1542,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
        emu->synth = NULL;
        emu->get_synth_voice = NULL;
        /* read revision & serial */
-       pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
-       emu->revision = revision;
+       emu->revision = pci->revision;
        pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
        pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
        snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
index bb0fec7f7e1be06b08fe83c1c386aa93f43b2d1a..e4af7a9b808caf0432e93491af8a383f919880ef 100644 (file)
@@ -942,7 +942,7 @@ static int __devinit snd_emu10k1x_create(struct snd_card *card,
 
        pci_set_master(pci);
        /* read revision & serial */
-       pci_read_config_byte(pci, PCI_REVISION_ID, &chip->revision);
+       chip->revision = pci->revision;
        pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
        pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
        snd_printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
index 6a0ddcf008848422197f2c7dd23eb1e6d66f104f..7c403965153b610780be5cc1c8c956d270f24ba6 100644 (file)
@@ -2110,7 +2110,6 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
                                     struct ensoniq ** rensoniq)
 {
        struct ensoniq *ensoniq;
-       unsigned char cmdb;
        int err;
        static struct snd_device_ops ops = {
                .dev_free =     snd_ensoniq_dev_free,
@@ -2151,8 +2150,7 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
        }
 #endif
        pci_set_master(pci);
-       pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb);
-       ensoniq->rev = cmdb;
+       ensoniq->rev = pci->revision;
 #ifdef CHIP1370
 #if 0
        ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE |
index 6dc578bbeec962245b2b844253eee21ca01a7f2a..11015178e2071004e101cfd59fceaaf62a0adae2 100644 (file)
@@ -1369,7 +1369,6 @@ static int __devinit snd_fm801_create(struct snd_card *card,
                                      struct fm801 ** rchip)
 {
        struct fm801 *chip;
-       unsigned char rev;
        int err;
        static struct snd_device_ops ops = {
                .dev_free =     snd_fm801_dev_free,
@@ -1405,8 +1404,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
                pci_set_master(pci);
        }
 
-       pci_read_config_byte(pci, PCI_REVISION_ID, &rev);
-       if (rev >= 0xb1)        /* FM801-AU */
+       if (pci->revision >= 0xb1)      /* FM801-AU */
                chip->multichannel = 1;
 
        snd_fm801_chip_init(chip, 0);
index a28992269f5e04bc993b7cbb25353dee7b0fc660..50c9f92cfd1bd5dd02f790830955ae952d660148 100644 (file)
@@ -2431,7 +2431,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
 {
        struct snd_card *card;
        struct via82xx *chip;
-       unsigned char revision;
        int chip_type = 0, card_type;
        unsigned int i;
        int err;
@@ -2441,18 +2440,17 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
                return -ENOMEM;
 
        card_type = pci_id->driver_data;
-       pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
        switch (card_type) {
        case TYPE_CARD_VIA686:
                strcpy(card->driver, "VIA686A");
-               sprintf(card->shortname, "VIA 82C686A/B rev%x", revision);
+               sprintf(card->shortname, "VIA 82C686A/B rev%x", pci->revision);
                chip_type = TYPE_VIA686;
                break;
        case TYPE_CARD_VIA8233:
                chip_type = TYPE_VIA8233;
-               sprintf(card->shortname, "VIA 823x rev%x", revision);
+               sprintf(card->shortname, "VIA 823x rev%x", pci->revision);
                for (i = 0; i < ARRAY_SIZE(via823x_cards); i++) {
-                       if (revision == via823x_cards[i].revision) {
+                       if (pci->revision == via823x_cards[i].revision) {
                                chip_type = via823x_cards[i].type;
                                strcpy(card->shortname, via823x_cards[i].name);
                                break;
@@ -2460,7 +2458,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
                }
                if (chip_type != TYPE_VIA8233A) {
                        if (dxs_support == VIA_DXS_AUTO)
-                               dxs_support = check_dxs_list(pci, revision);
+                               dxs_support = check_dxs_list(pci, pci->revision);
                        /* force to use VIA8233 or 8233A model according to
                         * dxs_support module option
                         */
@@ -2471,7 +2469,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
                }
                if (chip_type == TYPE_VIA8233A)
                        strcpy(card->driver, "VIA8233A");
-               else if (revision >= VIA_REV_8237)
+               else if (pci->revision >= VIA_REV_8237)
                        strcpy(card->driver, "VIA8237"); /* no slog assignment */
                else
                        strcpy(card->driver, "VIA8233");
@@ -2482,7 +2480,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
                goto __error;
        }
                
-       if ((err = snd_via82xx_create(card, pci, chip_type, revision,
+       if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision,
                                      ac97_clock, &chip)) < 0)
                goto __error;
        card->private_data = chip;
index b338e15db0d98d26b272a013fbd5c30f3a1abe40..8cbf8eba4ae9dbf4bdda50e9fb933403108767e2 100644 (file)
@@ -1162,7 +1162,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
 {
        struct snd_card *card;
        struct via82xx_modem *chip;
-       unsigned char revision;
        int chip_type = 0, card_type;
        unsigned int i;
        int err;
@@ -1172,7 +1171,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
                return -ENOMEM;
 
        card_type = pci_id->driver_data;
-       pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
        switch (card_type) {
        case TYPE_CARD_VIA82XX_MODEM:
                strcpy(card->driver, "VIA82XX-MODEM");
@@ -1184,7 +1182,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
                goto __error;
        }
                
-       if ((err = snd_via82xx_create(card, pci, chip_type, revision,
+       if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision,
                                      ac97_clock, &chip)) < 0)
                goto __error;
        card->private_data = chip;
index ea861bceaddfa3f8cf1281efe9a90ca69688d611..ab7a81c35705d1f4492c94a722fe0a1a1614190c 100644 (file)
@@ -2404,7 +2404,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
        chip->pci = pci;
        chip->irq = -1;
        chip->device_id = pci->device;
-       pci_read_config_byte(pci, PCI_REVISION_ID, &chip->rev);
+       chip->rev = pci->revision;
        chip->reg_area_phys = pci_resource_start(pci, 0);
        chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000);
        pci_set_master(pci);